All of lore.kernel.org
 help / color / mirror / Atom feed
* Patch for ip setting on bridge interface and vlan
@ 2013-01-23 22:12 Kevin Yung
  2013-01-23 22:51 ` Patch Kevin Yung
  0 siblings, 1 reply; 80+ messages in thread
From: Kevin Yung @ 2013-01-23 22:12 UTC (permalink / raw)
  To: initramfs-u79uwXL29TY76Z2rM5mHXA

Hi all,

I have an environment that needs to boot on bridged interface or 
interface using vlan. 

I found curent dracut release will by pass ip settings on these interfaces. 

So I wrote the a patch to set up provided ip options on the interfaces 
that using bridge or vlan. 

Please let me know if I need to tidy it up a bit more or 
add additional code to handle ip settings on bridge 

and vlan.

Cheers
Kevin

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
  2013-01-23 22:12 Patch for ip setting on bridge interface and vlan Kevin Yung
@ 2013-01-23 22:51 ` Kevin Yung
  0 siblings, 0 replies; 80+ messages in thread
From: Kevin Yung @ 2013-01-23 22:51 UTC (permalink / raw)
  To: initramfs-u79uwXL29TY76Z2rM5mHXA

--- ifup.sh.org 2013-01-21 17:46:19.000000000 +1100
+++ ifup.sh.new 2013-01-24 09:50:46.000000000 +1100
@@ -17,6 +17,8 @@

 # $netif reads easier than $1
 netif=$1
+use_bridge='false'
+use_vlan='false'

 # enslave this interface to bond?
 if [ -e /tmp/bond.info ]; then
@@ -46,6 +48,7 @@
                 : # We need to really setup bond (recursive call)
             else
                 netif="$bridgename"
+                use_bridge='true'
             fi
         fi
     done
@@ -58,6 +61,7 @@
             : # We need to really setup bond (recursive call)
         else
             netif="$vlanname"
+            use_vlan='true'
         fi
     fi
 fi
@@ -256,6 +260,7 @@
     fi
 fi

+
 # Specific configuration, spin through the kernel command line
 # looking for ip= lines
 for p in $(getargs ip=); do
@@ -264,7 +269,9 @@
     [ "$autoconf" = "ibft" ] && continue

     # If this option isn't directed at our interface, skip it
-    [ -n "$dev" ] && [ "$dev" != "$netif" ] && continue
+    [ -n "$dev" ] && [ "$dev" != "$netif" ] && \
+    [ "$use_bridge" != 'true' ] && \
+    [ "$use_vlan" != 'true' ] && continue

     # Store config for later use
     for i in ip srv gw mask hostname macaddr; do

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
@ 2020-06-23 23:14 Joe Slater
  0 siblings, 0 replies; 80+ messages in thread
From: Joe Slater @ 2020-06-23 23:14 UTC (permalink / raw)
  To: 'openembedded-core@lists.openembedded.org'


[-- Attachment #1.1: Type: text/plain, Size: 180 bytes --]

I have attached a patch which I could not send using git send-email which complained about lines that are too long for its taste.  I generated it using format-patch, so...

Joe

[-- Attachment #1.2: Type: text/html, Size: 1917 bytes --]

[-- Attachment #2: 0001-json-c-Fix-CVE-2020-12762.patch --]
[-- Type: application/octet-stream, Size: 13522 bytes --]

From 0ad5349424be97f2e8dc3c337367e3716bd2734f Mon Sep 17 00:00:00 2001
From: Joe Slater <joe.slater@windriver.com>
Date: Tue, 23 Jun 2020 15:42:20 -0700
Subject: [oe-core][PATCH 1/1] json-c:  Fix CVE-2020-12762

Import fix from json-c.git created after the 0.14 release.

Signed-off-by: Joe Slater <joe.slater@windriver.com>
---
 .../json-c/json-c/Fix-CVE-2020-12762.patch         | 204 +++++++++++++++++++++
 meta/recipes-devtools/json-c/json-c_0.14.bb        |   2 +
 2 files changed, 206 insertions(+)
 create mode 100644 meta/recipes-devtools/json-c/json-c/Fix-CVE-2020-12762.patch

diff --git a/meta/recipes-devtools/json-c/json-c/Fix-CVE-2020-12762.patch b/meta/recipes-devtools/json-c/json-c/Fix-CVE-2020-12762.patch
new file mode 100644
index 0000000..cbbcfcb
--- /dev/null
+++ b/meta/recipes-devtools/json-c/json-c/Fix-CVE-2020-12762.patch
@@ -0,0 +1,204 @@
+From 5d6fa331418d49f1bd488553fd1cfa9ab023fabb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
+Date: Thu, 14 May 2020 12:32:30 +0200
+Subject: [PATCH 1/1] Fix CVE-2020-12762.
+
+This commit is a squashed backport of the following commits
+on the master branch:
+
+  * 099016b7e8d70a6d5dd814e788bba08d33d48426
+  * 77d935b7ae7871a1940cd827e850e6063044ec45
+  * d07b91014986900a3a75f306d302e13e005e9d67
+  * 519dfe1591d85432986f9762d41d1a883198c157
+  * a59d5acfab4485d5133114df61785b1fc633e0c6
+  * 26f080997d41cfdb17beab65e90c82217d0ac43b
+---
+ arraylist.c          |  3 +++
+ linkhash.c           |  9 ++++++++-
+ printbuf.c           | 18 ++++++++++++++++--
+ tests/test4.c        | 29 +++++++++++++++++++++++++++++
+ tests/test4.expected |  1 +
+ 5 files changed, 57 insertions(+), 3 deletions(-)
+
+--- end of original patch header ---
+
+Applied from branch json-c-0.14 unmodified to release 0.14.
+
+CVE: CVE-2020-12762
+
+Upstream-Status:  backport [https://github.com/json-c/json-c.git]
+
+Signed-off-by:  Joe Slater <joe.slater@windriver.com>
+
+
+diff --git a/arraylist.c b/arraylist.c
+index 12ad8af..e5524ac 100644
+--- a/arraylist.c
++++ b/arraylist.c
+@@ -136,6 +136,9 @@ int array_list_del_idx(struct array_list *arr, size_t idx, size_t count)
+ {
+ 	size_t i, stop;
+ 
++	/* Avoid overflow in calculation with large indices. */
++	if (idx > SIZE_T_MAX - count)
++		return -1;
+ 	stop = idx + count;
+ 	if (idx >= arr->length || stop > arr->length)
+ 		return -1;
+diff --git a/linkhash.c b/linkhash.c
+index 7ea58c0..b021ef1 100644
+--- a/linkhash.c
++++ b/linkhash.c
+@@ -12,6 +12,7 @@
+ 
+ #include "config.h"
+ 
++#include <assert.h>
+ #include <limits.h>
+ #include <stdarg.h>
+ #include <stddef.h>
+@@ -499,6 +500,8 @@ struct lh_table *lh_table_new(int size, lh_entry_free_fn *free_fn, lh_hash_fn *h
+ 	int i;
+ 	struct lh_table *t;
+ 
++	/* Allocate space for elements to avoid divisions by zero. */
++	assert(size > 0);
+ 	t = (struct lh_table *)calloc(1, sizeof(struct lh_table));
+ 	if (!t)
+ 		return NULL;
+@@ -578,8 +581,12 @@ int lh_table_insert_w_hash(struct lh_table *t, const void *k, const void *v, con
+ 	unsigned long n;
+ 
+ 	if (t->count >= t->size * LH_LOAD_FACTOR)
+-		if (lh_table_resize(t, t->size * 2) != 0)
++	{
++		/* Avoid signed integer overflow with large tables. */
++		int new_size = (t->size > INT_MAX / 2) ? INT_MAX : (t->size * 2);
++		if (t->size == INT_MAX || lh_table_resize(t, new_size) != 0)
+ 			return -1;
++	}
+ 
+ 	n = h % t->size;
+ 
+diff --git a/printbuf.c b/printbuf.c
+index 976c12d..f9b15b1 100644
+--- a/printbuf.c
++++ b/printbuf.c
+@@ -15,6 +15,7 @@
+ 
+ #include "config.h"
+ 
++#include <limits.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -66,9 +67,16 @@ static int printbuf_extend(struct printbuf *p, int min_size)
+ 	if (p->size >= min_size)
+ 		return 0;
+ 
+-	new_size = p->size * 2;
+-	if (new_size < min_size + 8)
++	/* Prevent signed integer overflows with large buffers. */
++	if (min_size > INT_MAX - 8)
++		return -1;
++	if (p->size > INT_MAX / 2)
+ 		new_size = min_size + 8;
++	else {
++		new_size = p->size * 2;
++		if (new_size < min_size + 8)
++			new_size = min_size + 8;
++	}
+ #ifdef PRINTBUF_DEBUG
+ 	MC_DEBUG("printbuf_memappend: realloc "
+ 	         "bpos=%d min_size=%d old_size=%d new_size=%d\n",
+@@ -83,6 +91,9 @@ static int printbuf_extend(struct printbuf *p, int min_size)
+ 
+ int printbuf_memappend(struct printbuf *p, const char *buf, int size)
+ {
++	/* Prevent signed integer overflows with large buffers. */
++	if (size > INT_MAX - p->bpos - 1)
++		return -1;
+ 	if (p->size <= p->bpos + size + 1)
+ 	{
+ 		if (printbuf_extend(p, p->bpos + size + 1) < 0)
+@@ -100,6 +111,9 @@ int printbuf_memset(struct printbuf *pb, int offset, int charvalue, int len)
+ 
+ 	if (offset == -1)
+ 		offset = pb->bpos;
++	/* Prevent signed integer overflows with large buffers. */
++	if (len > INT_MAX - offset)
++		return -1;
+ 	size_needed = offset + len;
+ 	if (pb->size < size_needed)
+ 	{
+diff --git a/tests/test4.c b/tests/test4.c
+index bd964ec..288cec1 100644
+--- a/tests/test4.c
++++ b/tests/test4.c
+@@ -3,12 +3,15 @@
+  */
+ 
+ #include "config.h"
++#include <assert.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <string.h>
+ 
+ #include "json_inttypes.h"
+ #include "json_object.h"
+ #include "json_tokener.h"
++#include "snprintf_compat.h"
+ 
+ void print_hex(const char *s)
+ {
+@@ -24,6 +27,29 @@ void print_hex(const char *s)
+ 	putchar('\n');
+ }
+ 
++static void test_lot_of_adds(void);
++static void test_lot_of_adds()
++{
++	int ii;
++	char key[50];
++	json_object *jobj = json_object_new_object();
++	assert(jobj != NULL);
++	for (ii = 0; ii < 500; ii++)
++	{
++		snprintf(key, sizeof(key), "k%d", ii);
++		json_object *iobj = json_object_new_int(ii);
++		assert(iobj != NULL);
++		if (json_object_object_add(jobj, key, iobj))
++		{
++			fprintf(stderr, "FAILED to add object #%d\n", ii);
++			abort();
++		}
++	}
++	printf("%s\n", json_object_to_json_string(jobj));
++	assert(json_object_object_length(jobj) == 500);
++	json_object_put(jobj);
++}
++
+ int main(void)
+ {
+ 	const char *input = "\"\\ud840\\udd26,\\ud840\\udd27,\\ud800\\udd26,\\ud800\\udd27\"";
+@@ -52,5 +78,8 @@ int main(void)
+ 		retval = 1;
+ 	}
+ 	json_object_put(parse_result);
++
++	test_lot_of_adds();
++
+ 	return retval;
+ }
+diff --git a/tests/test4.expected b/tests/test4.expected
+index 68d4336..cb27440 100644
+--- a/tests/test4.expected
++++ b/tests/test4.expected
+@@ -1,3 +1,4 @@
+ input: "\ud840\udd26,\ud840\udd27,\ud800\udd26,\ud800\udd27"
+ JSON parse result is correct: 𠄦,𠄧,𐄦,𐄧
+ PASS
++{ "k0": 0, "k1": 1, "k2": 2, "k3": 3, "k4": 4, "k5": 5, "k6": 6, "k7": 7, "k8": 8, "k9": 9, "k10": 10, "k11": 11, "k12": 12, "k13": 13, "k14": 14, "k15": 15, "k16": 16, "k17": 17, "k18": 18, "k19": 19, "k20": 20, "k21": 21, "k22": 22, "k23": 23, "k24": 24, "k25": 25, "k26": 26, "k27": 27, "k28": 28, "k29": 29, "k30": 30, "k31": 31, "k32": 32, "k33": 33, "k34": 34, "k35": 35, "k36": 36, "k37": 37, "k38": 38, "k39": 39, "k40": 40, "k41": 41, "k42": 42, "k43": 43, "k44": 44, "k45": 45, "k46": 46, "k47": 47, "k48": 48, "k49": 49, "k50": 50, "k51": 51, "k52": 52, "k53": 53, "k54": 54, "k55": 55, "k56": 56, "k57": 57, "k58": 58, "k59": 59, "k60": 60, "k61": 61, "k62": 62, "k63": 63, "k64": 64, "k65": 65, "k66": 66, "k67": 67, "k68": 68, "k69": 69, "k70": 70, "k71": 71, "k72": 72, "k73": 73, "k74": 74, "k75": 75, "k76": 76, "k77": 77, "k78": 78, "k79": 79, "k80": 80, "k81": 81, "k82": 82, "k83": 83, "k84": 84, "k85": 85, "k86": 86, "k87": 87, "k88": 88, "k89": 89, "k90": 90, "k91": 91, "k92": 92, "k93": 93, "k94": 94, "k95": 95, "k96": 96, "k97": 97, "k98": 98, "k99": 99, "k100": 100, "k101": 101, "k102": 102, "k103": 103, "k104": 104, "k105": 105, "k106": 106, "k107": 107, "k108": 108, "k109": 109, "k110": 110, "k111": 111, "k112": 112, "k113": 113, "k114": 114, "k115": 115, "k116": 116, "k117": 117, "k118": 118, "k119": 119, "k120": 120, "k121": 121, "k122": 122, "k123": 123, "k124": 124, "k125": 125, "k126": 126, "k127": 127, "k128": 128, "k129": 129, "k130": 130, "k131": 131, "k132": 132, "k133": 133, "k134": 134, "k135": 135, "k136": 136, "k137": 137, "k138": 138, "k139": 139, "k140": 140, "k141": 141, "k142": 142, "k143": 143, "k144": 144, "k145": 145, "k146": 146, "k147": 147, "k148": 148, "k149": 149, "k150": 150, "k151": 151, "k152": 152, "k153": 153, "k154": 154, "k155": 155, "k156": 156, "k157": 157, "k158": 158, "k159": 159, "k160": 160, "k161": 161, "k162": 162, "k163": 163, "k164": 164, "k165": 165, "k166": 166, "k167": 167, "k168": 168, "k169": 169, "k170": 170, "k171": 171, "k172": 172, "k173": 173, "k174": 174, "k175": 175, "k176": 176, "k177": 177, "k178": 178, "k179": 179, "k180": 180, "k181": 181, "k182": 182, "k183": 183, "k184": 184, "k185": 185, "k186": 186, "k187": 187, "k188": 188, "k189": 189, "k190": 190, "k191": 191, "k192": 192, "k193": 193, "k194": 194, "k195": 195, "k196": 196, "k197": 197, "k198": 198, "k199": 199, "k200": 200, "k201": 201, "k202": 202, "k203": 203, "k204": 204, "k205": 205, "k206": 206, "k207": 207, "k208": 208, "k209": 209, "k210": 210, "k211": 211, "k212": 212, "k213": 213, "k214": 214, "k215": 215, "k216": 216, "k217": 217, "k218": 218, "k219": 219, "k220": 220, "k221": 221, "k222": 222, "k223": 223, "k224": 224, "k225": 225, "k226": 226, "k227": 227, "k228": 228, "k229": 229, "k230": 230, "k231": 231, "k232": 232, "k233": 233, "k234": 234, "k235": 235, "k236": 236, "k237": 237, "k238": 238, "k239": 239, "k240": 240, "k241": 241, "k242": 242, "k243": 243, "k244": 244, "k245": 245, "k246": 246, "k247": 247, "k248": 248, "k249": 249, "k250": 250, "k251": 251, "k252": 252, "k253": 253, "k254": 254, "k255": 255, "k256": 256, "k257": 257, "k258": 258, "k259": 259, "k260": 260, "k261": 261, "k262": 262, "k263": 263, "k264": 264, "k265": 265, "k266": 266, "k267": 267, "k268": 268, "k269": 269, "k270": 270, "k271": 271, "k272": 272, "k273": 273, "k274": 274, "k275": 275, "k276": 276, "k277": 277, "k278": 278, "k279": 279, "k280": 280, "k281": 281, "k282": 282, "k283": 283, "k284": 284, "k285": 285, "k286": 286, "k287": 287, "k288": 288, "k289": 289, "k290": 290, "k291": 291, "k292": 292, "k293": 293, "k294": 294, "k295": 295, "k296": 296, "k297": 297, "k298": 298, "k299": 299, "k300": 300, "k301": 301, "k302": 302, "k303": 303, "k304": 304, "k305": 305, "k306": 306, "k307": 307, "k308": 308, "k309": 309, "k310": 310, "k311": 311, "k312": 312, "k313": 313, "k314": 314, "k315": 315, "k316": 316, "k317": 317, "k318": 318, "k319": 319, "k320": 320, "k321": 321, "k322": 322, "k323": 323, "k324": 324, "k325": 325, "k326": 326, "k327": 327, "k328": 328, "k329": 329, "k330": 330, "k331": 331, "k332": 332, "k333": 333, "k334": 334, "k335": 335, "k336": 336, "k337": 337, "k338": 338, "k339": 339, "k340": 340, "k341": 341, "k342": 342, "k343": 343, "k344": 344, "k345": 345, "k346": 346, "k347": 347, "k348": 348, "k349": 349, "k350": 350, "k351": 351, "k352": 352, "k353": 353, "k354": 354, "k355": 355, "k356": 356, "k357": 357, "k358": 358, "k359": 359, "k360": 360, "k361": 361, "k362": 362, "k363": 363, "k364": 364, "k365": 365, "k366": 366, "k367": 367, "k368": 368, "k369": 369, "k370": 370, "k371": 371, "k372": 372, "k373": 373, "k374": 374, "k375": 375, "k376": 376, "k377": 377, "k378": 378, "k379": 379, "k380": 380, "k381": 381, "k382": 382, "k383": 383, "k384": 384, "k385": 385, "k386": 386, "k387": 387, "k388": 388, "k389": 389, "k390": 390, "k391": 391, "k392": 392, "k393": 393, "k394": 394, "k395": 395, "k396": 396, "k397": 397, "k398": 398, "k399": 399, "k400": 400, "k401": 401, "k402": 402, "k403": 403, "k404": 404, "k405": 405, "k406": 406, "k407": 407, "k408": 408, "k409": 409, "k410": 410, "k411": 411, "k412": 412, "k413": 413, "k414": 414, "k415": 415, "k416": 416, "k417": 417, "k418": 418, "k419": 419, "k420": 420, "k421": 421, "k422": 422, "k423": 423, "k424": 424, "k425": 425, "k426": 426, "k427": 427, "k428": 428, "k429": 429, "k430": 430, "k431": 431, "k432": 432, "k433": 433, "k434": 434, "k435": 435, "k436": 436, "k437": 437, "k438": 438, "k439": 439, "k440": 440, "k441": 441, "k442": 442, "k443": 443, "k444": 444, "k445": 445, "k446": 446, "k447": 447, "k448": 448, "k449": 449, "k450": 450, "k451": 451, "k452": 452, "k453": 453, "k454": 454, "k455": 455, "k456": 456, "k457": 457, "k458": 458, "k459": 459, "k460": 460, "k461": 461, "k462": 462, "k463": 463, "k464": 464, "k465": 465, "k466": 466, "k467": 467, "k468": 468, "k469": 469, "k470": 470, "k471": 471, "k472": 472, "k473": 473, "k474": 474, "k475": 475, "k476": 476, "k477": 477, "k478": 478, "k479": 479, "k480": 480, "k481": 481, "k482": 482, "k483": 483, "k484": 484, "k485": 485, "k486": 486, "k487": 487, "k488": 488, "k489": 489, "k490": 490, "k491": 491, "k492": 492, "k493": 493, "k494": 494, "k495": 495, "k496": 496, "k497": 497, "k498": 498, "k499": 499 }
+-- 
+2.7.4
+
diff --git a/meta/recipes-devtools/json-c/json-c_0.14.bb b/meta/recipes-devtools/json-c/json-c_0.14.bb
index 99fde87..1ee7305 100644
--- a/meta/recipes-devtools/json-c/json-c_0.14.bb
+++ b/meta/recipes-devtools/json-c/json-c_0.14.bb
@@ -7,6 +7,8 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=de54b60fbbc35123ba193fea8ee216f2"
 SRC_URI = "https://s3.amazonaws.com/json-c_releases/releases/${BP}.tar.gz"
 SRC_URI[sha256sum] = "b377de08c9b23ca3b37d9a9828107dff1de5ce208ff4ebb35005a794f30c6870"
 
+SRC_URI += "file://Fix-CVE-2020-12762.patch"
+
 UPSTREAM_CHECK_URI = "https://github.com/${BPN}/${BPN}/releases"
 UPSTREAM_CHECK_REGEX = "json-c-(?P<pver>\d+(\.\d+)+)-\d+"
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* Patch
       [not found] <06c7632e-9e21-7428-bfa3-4ec122f637fd@synopsys.com>
  2016-12-27 16:41 ` Patch Joao Pinto
@ 2016-12-27 16:42 ` Joao Pinto
  1 sibling, 0 replies; 80+ messages in thread
From: Joao Pinto @ 2016-12-27 16:42 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

Hello David,

A few days ago you told me to resend a patch
(https://lkml.org/lkml/2016/12/20/416) when the next-net git tree opened.
Is this a good time to resend?

Thanks,
Joao

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
       [not found] <06c7632e-9e21-7428-bfa3-4ec122f637fd@synopsys.com>
@ 2016-12-27 16:41 ` Joao Pinto
  2016-12-27 16:42 ` Patch Joao Pinto
  1 sibling, 0 replies; 80+ messages in thread
From: Joao Pinto @ 2016-12-27 16:41 UTC (permalink / raw)
  To: David Miller, netdev

Hello David,

A few days ago you told me to resend a patch
(https://lkml.org/lkml/2016/12/20/416) when the next-net git tree opened.
Is this a good time to resend?

Thanks,
Joao

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2014-12-01  5:35   ` PATCH Parth Sane
@ 2014-12-04  1:13     ` Greg Kroah-Hartman
  0 siblings, 0 replies; 80+ messages in thread
From: Greg Kroah-Hartman @ 2014-12-04  1:13 UTC (permalink / raw)
  To: Parth Sane; +Cc: driverdev-devel

On Mon, Dec 01, 2014 at 11:05:10AM +0530, Parth Sane wrote:
> Hi Greg,
> I have looked at the patches and documentation on how to proceed
> forward. But I have a doubt. Was hoping you could make it clear for
> me. You have said that you don't want unnecessary binary firmware
> files in the source which is really good. But if I how do I know which
> binary files are required or not? This is nearly impossible for me to
> guess this, since I haven't written the driver.
> Please help me out with this.

How comfortable are you with C?  How about kernel code and patches?  If
you aren't that familiar, this is going to be a tough learning curve,
and we should try to find someone else who can help out here.

What type of device is this, can I go buy one somewhere to help test /
cleanup the driver?

thanks,

greg k-h
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2014-12-01  2:49 ` PATCH Greg Kroah-Hartman
@ 2014-12-01  5:35   ` Parth Sane
  2014-12-04  1:13     ` PATCH Greg Kroah-Hartman
  0 siblings, 1 reply; 80+ messages in thread
From: Parth Sane @ 2014-12-01  5:35 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: driverdev-devel

Hi Greg,
I have looked at the patches and documentation on how to proceed
forward. But I have a doubt. Was hoping you could make it clear for
me. You have said that you don't want unnecessary binary firmware
files in the source which is really good. But if I how do I know which
binary files are required or not? This is nearly impossible for me to
guess this, since I haven't written the driver.
Please help me out with this.
-Parth

On 1 December 2014 at 08:19, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Sun, Nov 30, 2014 at 08:54:08PM +0000, Parth Sane wrote:
>> Hi,
>> Please find the attached patch file. I hope it's OK.
>> -Parth
>>
>
>> From 3a429077981db3a7cf96d1e503c0bbbc932cab32 Mon Sep 17 00:00:00 2001
>> From: Parth Sane <laerdevstudios@gmail.com>
>> Date: Mon, 1 Dec 2014 01:55:47 +0530
>> Subject: [PATCH] added_missing_driver_code
>>
>> ---
>>  drivers/staging/mt7601u/TODO~                      |   10 +
>>  drivers/staging/mt7601u/common/image.bin           |  Bin 0 -> 67936 bytes
>>  drivers/staging/mt7601u/common/rt2870_wow.bin      |  Bin 0 -> 12288 bytes
>>  drivers/staging/mt7601u/mcu/bin/MT7601.bin         |  Bin 0 -> 45412 bytes
>>  .../staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin  |  Bin 0 -> 47032 bytes
>>  .../mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin    |  Bin 0 -> 51944 bytes
>>  drivers/staging/mt7601u/mcu/bin/MT7650.bin         |  Bin 0 -> 59580 bytes
>>  drivers/staging/mt7601u/mcu/bin/RT85592.bin        |  Bin 0 -> 35060 bytes
>>  drivers/staging/mt7601u/mcu/bin/rt2860.bin         |  Bin 0 -> 512 bytes
>>  drivers/staging/mt7601u/mcu/bin/rt2870.bin         |  Bin 0 -> 8192 bytes
>>  drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin     |  Bin 0 -> 12288 bytes
>>  drivers/staging/mt7601u/os/linux/rt_linux.c~       | 6215 ++++++++++++++++++++
>
> Take a look at the file Documentation/SubmittingPatches for the proper
> format for how to submit patches in a way that we can accept them.
>
> We also don't want binary firmware files in the kernel source tree,
> those will have to go to the linux-firmware project, but only the ones
> that the driver really needs, not all of the ones you have listed here.
>
> thanks,
>
> greg k-h

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2014-11-30 20:54 PATCH Parth Sane
@ 2014-12-01  2:49 ` Greg Kroah-Hartman
  2014-12-01  5:35   ` PATCH Parth Sane
  0 siblings, 1 reply; 80+ messages in thread
From: Greg Kroah-Hartman @ 2014-12-01  2:49 UTC (permalink / raw)
  To: Parth Sane; +Cc: driverdev-devel

On Sun, Nov 30, 2014 at 08:54:08PM +0000, Parth Sane wrote:
> Hi,
> Please find the attached patch file. I hope it's OK.
> -Parth
> 

> From 3a429077981db3a7cf96d1e503c0bbbc932cab32 Mon Sep 17 00:00:00 2001
> From: Parth Sane <laerdevstudios@gmail.com>
> Date: Mon, 1 Dec 2014 01:55:47 +0530
> Subject: [PATCH] added_missing_driver_code
> 
> ---
>  drivers/staging/mt7601u/TODO~                      |   10 +
>  drivers/staging/mt7601u/common/image.bin           |  Bin 0 -> 67936 bytes
>  drivers/staging/mt7601u/common/rt2870_wow.bin      |  Bin 0 -> 12288 bytes
>  drivers/staging/mt7601u/mcu/bin/MT7601.bin         |  Bin 0 -> 45412 bytes
>  .../staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin  |  Bin 0 -> 47032 bytes
>  .../mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin    |  Bin 0 -> 51944 bytes
>  drivers/staging/mt7601u/mcu/bin/MT7650.bin         |  Bin 0 -> 59580 bytes
>  drivers/staging/mt7601u/mcu/bin/RT85592.bin        |  Bin 0 -> 35060 bytes
>  drivers/staging/mt7601u/mcu/bin/rt2860.bin         |  Bin 0 -> 512 bytes
>  drivers/staging/mt7601u/mcu/bin/rt2870.bin         |  Bin 0 -> 8192 bytes
>  drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin     |  Bin 0 -> 12288 bytes
>  drivers/staging/mt7601u/os/linux/rt_linux.c~       | 6215 ++++++++++++++++++++

Take a look at the file Documentation/SubmittingPatches for the proper
format for how to submit patches in a way that we can accept them.

We also don't want binary firmware files in the kernel source tree,
those will have to go to the linux-firmware project, but only the ones
that the driver really needs, not all of the ones you have listed here.

thanks,

greg k-h
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2014-11-30 20:54 Parth Sane
  2014-12-01  2:49 ` PATCH Greg Kroah-Hartman
  0 siblings, 1 reply; 80+ messages in thread
From: Parth Sane @ 2014-11-30 20:54 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: driverdev-devel


[-- Attachment #1.1: Type: text/plain, Size: 64 bytes --]

Hi,
Please find the attached patch file. I hope it's OK.
-Parth

[-- Attachment #1.2: Type: text/html, Size: 103 bytes --]

[-- Attachment #2: 0001-added_missing_driver_code.patch --]
[-- Type: text/x-patch, Size: 389781 bytes --]

From 3a429077981db3a7cf96d1e503c0bbbc932cab32 Mon Sep 17 00:00:00 2001
From: Parth Sane <laerdevstudios@gmail.com>
Date: Mon, 1 Dec 2014 01:55:47 +0530
Subject: [PATCH] added_missing_driver_code

---
 drivers/staging/mt7601u/TODO~                      |   10 +
 drivers/staging/mt7601u/common/image.bin           |  Bin 0 -> 67936 bytes
 drivers/staging/mt7601u/common/rt2870_wow.bin      |  Bin 0 -> 12288 bytes
 drivers/staging/mt7601u/mcu/bin/MT7601.bin         |  Bin 0 -> 45412 bytes
 .../staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin  |  Bin 0 -> 47032 bytes
 .../mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin    |  Bin 0 -> 51944 bytes
 drivers/staging/mt7601u/mcu/bin/MT7650.bin         |  Bin 0 -> 59580 bytes
 drivers/staging/mt7601u/mcu/bin/RT85592.bin        |  Bin 0 -> 35060 bytes
 drivers/staging/mt7601u/mcu/bin/rt2860.bin         |  Bin 0 -> 512 bytes
 drivers/staging/mt7601u/mcu/bin/rt2870.bin         |  Bin 0 -> 8192 bytes
 drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin     |  Bin 0 -> 12288 bytes
 drivers/staging/mt7601u/os/linux/rt_linux.c~       | 6215 ++++++++++++++++++++
 12 files changed, 6225 insertions(+)
 create mode 100644 drivers/staging/mt7601u/TODO~
 create mode 100755 drivers/staging/mt7601u/common/image.bin
 create mode 100755 drivers/staging/mt7601u/common/rt2870_wow.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7601.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/MT7650.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/RT85592.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/rt2860.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/rt2870.bin
 create mode 100755 drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin
 create mode 100755 drivers/staging/mt7601u/os/linux/rt_linux.c~

diff --git a/drivers/staging/mt7601u/TODO~ b/drivers/staging/mt7601u/TODO~
new file mode 100644
index 0000000..891bd12
--- /dev/null
+++ b/drivers/staging/mt7601u/TODO~
@@ -0,0 +1,10 @@
+This driver is functional and has been tested on Raspian(Debian Wheezy) with excellent expected behaviour.
+
+TODO:
+	- kernel coding style
+	- checkpatch warnings
+	- dead code elimination
+	- device tree bindings
+	- possibly eliminate the extra "hardware abstraction layer"
+
+Contact: Parth Sane <laerdevstudios@gmail.com> or <parthsane@laer.in>
diff --git a/drivers/staging/mt7601u/common/image.bin b/drivers/staging/mt7601u/common/image.bin
new file mode 100755
index 0000000000000000000000000000000000000000..f357c59ab407d3a24c6032ac955403bae675806b
GIT binary patch
literal 67936
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
Q?_95QEoy5MS?2HbA3OKtssI20

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/common/rt2870_wow.bin b/drivers/staging/mt7601u/common/rt2870_wow.bin
new file mode 100755
index 0000000000000000000000000000000000000000..bfae0f0ab0e30fbf06a1e3a32cbe94238d0439f7
GIT binary patch
literal 12288
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
BP2~Up

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/MT7601.bin b/drivers/staging/mt7601u/mcu/bin/MT7601.bin
new file mode 100755
index 0000000000000000000000000000000000000000..62b3894310da4d8c77b97f6b8df9ab6d3d6b28d0
GIT binary patch
literal 45412
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%0Do59Fx}3^-@EU~8ke>wpQ?=D&
z<&9HLQMdcc>H^RA9T#>NqZPC;2|9+PWJ~+7R#f<CI3Q&wTuY^Wusy@(=gm6i&~JpF
zWKds>|G$~6d3=!-JLn4%?Zj0$pRMh8yr0%@JD#b}+4I1uxq4aKgYfospOMbxv@bs4
zZolo+^?H5_75z1RMOgJ)6`{9*8xS(rSijT317Hoe(!%;hE4D$$8xlsjR{gvcJEVW`
z-x+h<4u3E?zE2mP1L^WjtOqCW<?$b4=am$XwojY{LAShwy?37?vuz9de9p;d*fw~L
z)fqMJWIaokA?`+PiHK3xp7<I@UDux)fAsyda~T-(Kj<@zG2ezU-`u|V)O~sd?CJ@$
zE#WPU&Eff^5^WNi>2k#G3ub@BJbem@eqZpm*eyho?hR8?8MDXg^+o0=Q#SibNfs#l
z(O6|r{qFPFY37W}$wtm&M$QT36pzc9gq(Fo&H!?zj>~Z&XT8Yzo{AiJ4+y*({Y*yA
zcVd+>io8;LA0yt|bDS|vr2KtMTWe&bc}L5UmZyd^tOn(-H<YM90vdi+5<CWSx%Rs5
zZY~91vs$amz&%W2wR|3a(0?12aJouaYVW+@nwmIl{_7b0N=u}cp9<d8@)7RVola_4
zqEEvQJDuFARZ&LNK!}zl*QbxdI$8;j?rkb1Tk*RE@%adEMd(KuK=@6B%MgYT-i`1c
zgsTv)Mz|K?0|*~MSdDNa!cBho6cC$K`PnfrH(SIjSsyrHi8&e`h4d`;Rj~@e3&*fW
zmPwVkVc<D;6WRi&lg<l?HU23|q?2#40PheZ0FA-B%$D&-I}Y<J`Appi(d&&tQWF>c
zw+;z-f@OrQMz4Z@q9>zQA+vs=SIAH4@bqwV%4<~*+otBRt@z!7_<V%7BJ?8+Ap9o6
zWe7tE??!kJ!c_=YBV3E{0fdhrtVXyI;ilwXDeNTBiPB|-^zePqM4cyZg~w?s{75DU
zPt16$K8No=IfoxS=`wEaH0oCyqfW)GW|d@{a0{9MoP<&RyUARB-S|9=H&@3y1jdd5
z+<Y!CTVG)MznbZr1MuxwX_Wq!w)PDhc2{U9WH&F=#cMXuP`1Wd5iBjmLOapixJzio
zvAz?`eZr3AvEuy+=M1g^-njxCGX-V#3Yc|_%=n7pD;FL&`%V=i?*s=G>sL~EPcMIu
zCFpjdP)=ZFGH+)Z&`i-P$3xCNILk3+Zqq41oSa32gC}iK7XPP;#HxfBwhL^?m8D6|
zu*rOJ&Ofi$0H<!_OcvDf6i#bCpKm~geFP`i9<#mirN;Iiv40pGKiK}jiS#`Wp7Jg1
z0|#9x?Sp;L@%jSYXSH<io(E238@qx%elzxkQoYdNjg!C|)3F~+!hTRR%IoLq(@ai8
z!ul0fY=aJ2+~WEfR_u_TD!A!RJ8s-LT4#t|!<(6tu3P%E*z@#soCC?wIPlWI7e@j;
zN^txNjR`o_JGJ{*9d<v>_?n{K&-N*KTCL*M>YCN&N?IC$HPg^X(zCGx2$`12N|wZx
zQmMYh(GsTlqJ%0m7E$6Lb3?z|h}=!hmCZSny5Y~NC<1z;#7*pZ?lC1F*PU#+(QC1`
z2HIYOkkbqa3iq3~K4IvDl0k(FTou}r*ayA}9a3_YNv&aZ<7Uo~ry{l5=f<AV5hN@p
zwhG+Z16nMLx!V`F1$Mu-drK@L_;<|B3Sn!^;|JOn$LQPQ#*u__^OOA=GR}L(%%`ix
zT9q-U)1`gbtD&_r$%Xl?+pVq8W-2n-KKV^X#My^y50j%c;y$zHWc}<{uI<criC?S-
zubB&v)iC7D4Y8UbZLoIOHlz&NAyGg^XRXLPguF$#P0rzSgch-C8lro4^O&;xw<FT-
z1u<XUF9+nhjj>A2KVs90Vuf1DfWqF7(GffALTPu*=bBHZ{_9@XWHQs`V&yn5y4h90
zysk;)HkYh5oF8`wSm;y&cS@z!fO}}x>S}<#6e=K&qf>-L!m9WpP>kftmm09D_G4xy
zsHt0@5SlscqRn3K#}1c=HHVfF^%biHVLO4(nfsT?Z|G10v-UozVe*Ge8q>eNRIfv?
zm_wZNOWlGF#LDtxhv5{b;esc+)dFdakf3%hKH)NDHk7%4JU{ds=h)l&=eld<-h4e1
z?Lcp?I|hqQT%9eg8P7??D0xKmHeOF152LWjq6Kh>y2BU=)|nz}`v8r6{C@VQSc1J0
zoqtio%pHo&AC%awh;1I!0O?b%EK*c=G`g~`K9;ZHhPyUHv!g~ndj-^)5Iw^xFf;5;
z+5E3R!HnIE8S`SsZgUlYvQ_d`lu})jq}G@ZUnWHt2FpoKOyT)RbCWVxwzjW5JGP*0
z*`C|lw#4?u>S6`41*{+#BzgRSHYwHt-=Du3v@xH%1qBG4LNlpicEv623wg+=E-LNQ
z=K>m{l#_b)CzGe7M8bJYfk)9-Z|x&xx5i1iFG6Pf8p#|VBR9D6Nxf^0);bxSW^$a6
zm*`9Gm#|KQ%v?<`k+=V*6>kl=I<*Fts;JUF_}q=@HdUez9^ur0rdWH>3fG7b9N-RD
z(3<_5%ooZq!(u;ACkwR)XjUg)&?<4zQl^L#U7CHJLqJd6;3#5rcWU1PeA~y%M8=zQ
zLb5o85<(JyEMmzRfJEHwfCk?fCU%SgnyS>?ms83l_!RzaVIOwy`Q&--er9Tmhmxk0
z?3LtsQwuV5KT~4)Lc4-jME}_Gynska1y93DWB#yOPmEh?fT8v|P?L(*DYzeb=Kbbf
zlsHnd-OOs;lI1}AfV;ADoQzoeF=|4p2*YsN5|5S$=-I+Bf#z!MpQ7z3-Y01Nd2Eq2
zVn|$_)tvnB&6bZS$xZq3KvG5#^xZ5EXwZ5iz|FJr$B+TUi*}(=EjXLhF=_t>oPFZn
zq)Um_81~_s_7`Hdmgl1jVN)v><AetGJSf$WPW`Hc+ne>I^#uXxpw#pqXX5924bKaK
ze?TM80anQmcelJiNlr?36?r~6V+P+H0Ti%-Xs2+eaon82!{bx2-@KS#Pte!LRLPk}
zN$XVHqm~9VVLuM9t0$)BIk8P}4qz{Yk=gLZ478};dHc(Tq^@dOrYifsOC{`6L{Xa8
z3W++pajVpJI(B~u7VxvqbN`8cp|@{)2-q&g=scJwH<clCn{-gYMj;k+1sWshjY#)*
z!J1?AixXtPSk&`;fM|cju3y}L1791EYHxkt**}@r1!U=;-dFnJHGAUWO-BQnUc3Y<
z;e8d9{uW;tki2)|`$7I~)VSgOjD9EI5|HIm{-c0=^tMGrF2u^r4`fOm=%WC24uK=M
zQEMJ*ZNVP6ARuYqMX$bow~vz9=<RiU&FN1Ee=QEkS_JjW(Q6^f{|If|gf@PTHt;Hs
zG!OM}3`j@u2B~xawU?syzoPasqqZNl=b`pO)V8C9AGPm5?HFp`iP}F$?PUS!$R*^x
zXkleV7vY=n0?|_#JLKOJnPSAA^ZMhctAd|zLEY?t<T(r7a-TKhuLJW~*?2u5BkJSs
za2Zi!Rgec#abH-i`2??0eF)me%`$OASk8!1tU7Ynhcb!&Pn@aRUd=Y_%WAD6^ftpP
zwh~sc4q@qvYQkcOxBEQs%Fjubi+cEO4{n)Fw#rA1veerk$27bRL82bWVJaX(n^BGb
zPnz$NV;<46=)t%Hv@%1Eb@)r|C`<G3LZ2t<4y$$Ig;sGoAZTBV%8X$h149pD4DjZG
zEePB+JUv5{jantn!wc96j$u;PgFSJSU+NFSb8G3g_x6{Fl@QLu3j(#t(+sh)P)2ap
zWM33zyeXAD66-`Nc0#QZ5P<W*e)?dK!8?IrCF=9d$BPV7h8%{w7|Lc2B%;1BfuBVg
zu!ehX(8@b8@(h}fGZtTTRamNnT@bxFE%-u$Ti*4dv;y*h8g<LF;7ydD%mb`Q(~CyG
zjWT{~rC`keGMeKCY<Wg2B<k*LZ2d;e{oH1h(8o#u7I*7wF~RS|h;T-O{C^wGFBSR8
zw)KBbro%RBVlqs#DSQOS_iDi&26ofKOSKizTcVYn-TF~s+W<7-(Kc|KU4PkXdn~mm
zTAA#x^&9%F$<ls`+FoNUZj2?OKQo%+R*<6a9{nyA-^n)MuWLdYO2T8%l)JNgQ6ll(
z(L6Wk%#D;MMpFdkjkY2%H;$5I!_EVI)#gAWm@%po3h78iim-qQssYs{;ef}Tq{E}y
zz`^~}X+rMEB<U-lf}5DHeWG_(Pbu^dv!>8Al6sn;bBoH{gb5C5oMk1?*fdC*s0AxK
zUJVlKTvb-f5?zLu1-e~JWeKN$D&|&gu;%zl2TF-~T`=~#DfT_jg1%rnPWUspjPi=*
zC5#b?`+yjQ9j9jVusT%ma<%q4vFmejT7j=^ec}so@y5h?o@soU=SdsP(Fq?cc(-a8
ze_A*%rO#LDAiy+a_Ov#u1f*NTKN-H1^-ox7D~$0F-T|LMA#nj3!{gV&!I<6%$zV~h
zJE?V=SSFX7j<!w}CksON`TzL=Qsdocj8L4FtN^_yev{g}yDFQ=&4DVJET|#`t3dQ2
z(!46e2{uy@w}~8)F7`Ei8zq5FczjDC#YWQOa<3a<h7m$vfS)u8;hZ2q5<{p<^uL&O
zzxZY^@G()jiTw}USFsBoY{=acUB&EwSeOD`jF-Q^>?|(X#(+c%jQhZUw?2FU(5EXE
zH^xQyEw<{o!$%}y_V-k7@2ofQEsy(7(rWi%AKr+x#=XK@*|d)JX$#<^mx1$Rx0bId
z-H%zVfKq}t)EuIP4J7Qt`FdK+f8b=SwmaKADd?7B##~0UnAE)`mM?BCMBM?EDv&r+
zBd<oaSY1?#Z0Xi;TON29w4h{>P^$!gt&o*w&f}<es!=Y8vyY`)+1%_};X^8RCKB1o
zS5f0tA&1gEVbr%3YbRWW+!cU$0!iI=b9|!MFNKd~nArM3t(hcW<f(UV`&zRj<c1a~
z*0nfmT?0<ZaeAS?ELOKjsnY)mp3`na>l5Gi>FZEKKAOy5rGLBm*l6iWy$WX@it&1h
zD7{)=LERB&v%0(wx0LXPiPh>_J&0c9(RvT)i#}8DL7k$8V_c1I>o<J{u7~tlsNo*%
z=^ylBz)45pd>G!SZg@*2;e14&LTMZ)L(QONT`_!TlX=y;Q(#D$Pqw!0a?K)Jbx?hB
zwF>$+{3o%Gg&1!4mes?&I@iG&UJ#fc-FHDFD_JT$_gTx@f1ii1JuKDR)aoRUF#C>Q
z?u_{k;!Vw_ZUr8Dii$iH>Atr4iHj0lQ)u|`UDRSPM_+D#;G%{)@CGF8mv(4jRe|L-
z7n5!OdnRIb^fLeLv<uRX9&uCPl%3$TI0pZ(_B_yU)jK~MlqmVwDdcP6{V3Knbbr9j
znf<gz+w+88ZuGGXzC?;qXGHWMd~xtDr-Iv<slaOHu;hDaegZx}crgV2mh)Z8uqNUD
z5&U-N(?@cgJ7aXVst8|I+}*T`9si=_S|w2?tc~D;;#~mTPqI#60RwLF;G83uS4P>0
zz*h?FWpa!A^@0&iozCnc1vV|4itvIIi{K@NJOi&O7^iGODsW-cd)<MU{q51wx4kV!
z@`v9HN?vj-U3e5&em5f+dlqLMD@AL7KLw{dqpd+Nt-WCQ+roP|ML@w83`^Z_CC4D%
zCcqdh&tqWJw4<0eXQ0<(AIN|vsrYE08qUkS{9@jV1QsZ2?nM(0@w_1L!|gc7!`&xt
z=XtRj&2Qpo8_xFex^EgMkaG98NvA#$`D|tH%xD50pvs#gxIL9;c%}fGqO_PrLw+o)
zSI}!l>?|~Ko4~Mn#{;z~cw3lOkd`)_oAPhBmh6!5+RjI#zT|ENo_oB~eww7Vy=_o}
zz^BaQxIqbj7~!iqfd}$@0~^Ap+CC_C-^mKU93x^~K&R~VS7XN4Z9T;EG2S3oaDokc
zFya9#eih=2toS6veO5dRaSHs1^4W;bv*M!6Tr2KEe2$2lvNK_j>_B)UoA7QqByWF2
z$r{=ST~>)c=x<ci;reh>eMa;EPTAE9JiNxPL^m#cbAb36VSK?|Z$KL08Dyl+uw_WG
z+f4m2b3NWen&%JZyas({I_NNy@4@<;^3vki{jmeFjet+UT8dkYNm#G5;sVwZD=uIy
z6medNm>bdp17`TdYNM7o$J&M55;59w@kxBKl`77rDny(YBDT$l<uMONUt++QLcCZ*
z^J7l5FbO4!fk)ArXqkypR?CA{T$JfBY748VOT_%RmIJ%h{Ma@AO593WLpHE9j+0+L
z(?`f4LN~%85u)uP)GEXG2z-sO!iS)Hh_b_SJ%t_fiQ!rote|yI;$}xkyuT6p4oUT#
zZJQdZCka7ao|oIEe&Fc8k}XC%*K%RAu{guPWRU`HeVNX1DO|a*b8J=US0XQqEgoNf
zXmZm(;a!Jci94rU5&6U8YT(2gXBrmld#n)ODEC9;7%9fRzD;csZti{3w)oaQ>AJvl
zqChUbVAP&0Y8fw78Edg^F;BytX_0@)zzFiu+Rw~>5L3-|hvjGiC2`>oVD~`>YL##8
zV}#Pna`WP2if<)SzUd{T&`bEbK?z<t%7C`~7)j-+c$fCUKwbPBU&PG?6F2$nGF{?O
z#9A2{H&&zkb>nd}EXrROl2HC$qTrRA&tTIi|CRCOM@0Frgz|y=ThRUju8hZ}e)Xm|
z1KVjX%6x7PMkdp%GaMlqvjBUXs3*#due;R)dQ$@(-~U^ZwhY{XdW>+~3;}zSIs6cS
zU-2r~{<g($<4v$luLUxJbG!;>;v6)Amr~e<-dRH#Xc6-L#A?we)<w}!I%3&IEDf<q
zMog>=ml1Ptu?~xdvWz@X@{o#H7FIyfP$pv8Mr@*yE7HX4-(r0fT}T!B2~Ou3^kQ(_
zkrd&-7Q?x>l6Aq3H|CVsUW5NYtEg9CD<I%GCO@t`zXJTw@?!#DJcgFC(2^4E<Z;|o
z!3v5U^Ofe{rm9`BAHi)H)Qzncyxa#z^cQhTVe*R!hrm7NU<7uPvx57Z9HAHx79&qs
z2*p^&uYHkzoi(x~AE>j+i|<LIJjxVWBQ0TmD^+kb!Fk+PX}sZ&xk0`Wigt5Z3d-ao
z%?MF;k^u+a(Lj2ES=NXZ!;)ycql8*6q~L{KVL`;WQt%w#2JkgPW*KlZ#I6v04YLf}
zo4E0dI=DlIT4kaRD-tCX+#0j`E#Mx5k6Jawir(}q*oUUqeA51cubRvYtif*U)-Q+_
zL|fp$2FDTmxVwg_G{n?rJ~3W0kQxPty_OQkjeI8T$-jH=m2+}K+NRg2d&3n;TI0oN
zp&F2{0}Yxqd<A&B;5L&Hy3KHCf|x1L5N6S$Fq1Y#nn{}?X40mJImCN%2vbo$--sDl
z6tO{ZIy<YkcvuqjCg{xA_40(aYwh~0C&w9iiE=S78Oad}Y3n?0VkiI3!H1W5UNb=n
z1@=sPxNPg8<d^~^uJQtI7w^OlNwm!6Z0ZFs&*B9_LczO+R^BD(=S|L?{}3*Rw-V$c
zUNEd#)OcBF&uk^2hdwOMjiW2!`@e^lLHMX(6n~##26{907BLz_4;Q$)`3v>-(EMCy
zQwyw4!B`C|5T&*0qLh$oB9;vSV`03IqOTUllo4%gP6s4Ntsig?Zu-lCRV3w?c+KgL
zsXB1QRJ@9>G6#6L!{B`u9~qNKE!pM#D5T)&nz`o@@-u@s^|AZ$-dP5J88U)+7wht{
zX3*r%dkZl3!#GjCt#{s_tvw3abJnhpk~BUn{qg+nhcK3(3;$+zn^|@Y>Wen9w~9Q}
zyU9D-RmhuZUgM3s{(8C??<El3e($=(#XIo&@R(1OA!l9Zr?5?UGrI@0o8=4zcOw~(
zFN`Z$H!Jvi78acv5dJJ$MSl=?X3rr6`o@lnKhaj$|3W0}$(gA2I$lf@YwPD$c(}J%
zSx#PKMHjXqbs8isYYpQ@I$n!nDZST>%w~&5w&KexzJ_Nb)-c?F(!0@yD78nV56$KU
zLr;lRK&6h)QF<hgkj`8OS(?J}ZcTW40(Q+Be`y3<5Ig32mpn3?PHIqS0aI{}nsTx3
z5+B)evHoK1;HII?XmbyG5n8=9lQ^AImA#q=a}$SD$LM|4ifgsz8IX@p60*p>32Egy
z+i<FW6*!1=??@u0-#(;x%hoz{*RVs+9+vJM)K;EL9Z~!&PViSIaIbhk8g^Vty;rSC
zp|kl^Rxj3I#b0V7u5xJs-hzG2#0%tHA=e+nn!m<~#j$d)!HL)`b{I0#HT+t{4jHkp
zAQlxdz%Jy(=dJi;#GkX`S0LVP#f6O7DcVJOArD8axTxD^#f6O7YW8i>Wwjw8&I4a^
zlhc4@9ypVm)S=CJ{942+jM!HYn<rud7Q_p!_~hMBS+OgS+F`|$5~V0DWK|(iCTj|b
zavo1gl=J+_wT>0kmTB?He}Kdof#xOF{liG>b}c6o+A?XT2r(+=)G96f7sV+kAs)m)
zKcXaBs0Qy^x9u_qhD8cS{<`2d!?W98c-ih_(2uKXMw0y-ef<nA=A(t5BNP(tVT6LO
z;2SM?tQ4^ejgxgp`yqzhe%$bdNvWsxGd69;>)%aA%hRxXu4J&jbQ09|_LdBmhX_-T
z!)}S4CMkytS-Hg8AxeyTlkqLE@G~p@=cp;aDmXq9(CC8WAI6vV*}ag*#b}LjA0Fc!
zBN#a(H+Iy}*Z%n7V7choX#dOl6+0FBMe7N~&@*C!Z!H{aac~CSiH-K#x90t6_PGXq
zI=(KRvv1E^(v;YUcLwcr2KgQD{G$zj^&yQv8`#S-S+2PXw=_UI?l@(u2glm#fo1yP
zdTF>k^e9u`bmATha58SSS~Ozp|6-2B42W<R!hb_J!}?B!$#g*tqFgderWaf3Rw!EG
zv#_Vi$+>*3)S!bTJs=#A1xA5^e=})lM51}E&Zg#jhrlVsYi2IIo@j86nv{O=?Z6(A
zN7SL8^86%?S-s}#!td6E%nC)j=8TEfFTl^A<{PaKSgq&iX_usXhrx$L+hTu0k7&E#
zb8TDg4bB#0!pOx-kHsT$vefHYpC4Cp?BJR>p(Bl7fXu>;@J`Wf!}81Dzhvhf@7gZd
z-uf<1OVjZF<XSBadx!!(j@DCfl@xH)4L2(dg(CHHA;Gsn&%wz=hNof;H29b6#VhoJ
z!UT^vY~o>z#s+4?Z;vfWfsO>K*BxDlysD#+(#RdbY;zU#&J(++WNZHjJT@iV#5Vl#
z)K(AQ8`zt8-CR9FA{0Gvyd6_0T?8gEOLl%e(#F;h-h79wY3+nYJ?z1`qTb;)pNL%)
zcF-)`MR+Y)%2+|BEQg(Ma01Fg${fr<=ryEGYnK~LN6Mbw;-NCkgrSK*iWAaYsU^+f
z^Z;wIXy|$lO&8%;IJ7Q=LMESN#I8kbvJsn!*cC=haC%cK5o^=bN`yQvr1hd9!Ltml
zWH?joMcpTjxy7D4=ro}jF<ujJQO(0T22$YlvEY*YX38ex?{zFne0=};-zH^3=pzly
zi&{>EA|x?bw`86DZiCms+teJ-ghONV#S1WlRRRK|Or;UCGqJ<1z|A8ed4`R&BE&*w
zt|5;GdyBLp@Z}kJ4=D%l(fN^g%~pZ`S?y7CWo|tbV0aN;B{!q)BIJwFehqP-h=T$j
z!uJ$>2a>X_VTE(U9)SFjX{LrWu^P7?gd7Dq)(tzEnL9j<LqlWuHd5o76Vg-~^vi|f
z)oJMcLgK12-krWEW)CMa#e=ww-kfo3oRkdwFz_(39si)>L-r86SF~+nM99_y)9Q0+
zrCSac5D7ay{vrgoU;LqkF=5GDD4-q>@r9|kzM1HwI|k&iiwSGN6nKkGtrzchSrUw|
zl$7yW<P_7Yl4-QE1n*ZN%<G<7?;e5|ndYq9lEhh(=9WB7?%+a;dq|8NJK;2563SzL
z6JI%Ee-)C&+T`1;0&_!C(Zgi%Ho#cVgZ9B%c8#HVk6J|dk4_5N^O7;+YsZh|(p0X5
zCb193>O;p8Sp5~ODK=qE8MT#MOhSN`!k>o|GoySK&hfo`DV)k+t=Sj!JSmWA^z~#Q
zn+Uti#s31*W$c4+HeMcn=KmI6F7zbfb0qAnz}TRHF`NzvujHh(X-FbtTGW!g<a=0=
zD!2(=tgtJXOIUz~9uJ?b)v;T|3?VL7cCr0UHciCC*As?sv8IJYb;ODbSq!vhq`Nr&
zVi8uISbvz|-r|92xZxhB6w>hzLGkm2c4n<gBY$X`VYfemyFBOxJ<R8YMhUD|v|DDh
zDpuN9Ys_qo2~V?|MOlPm{f)K9JXU-73qXQnf33G@6Vo3O+GujTd^1*gj<A2nw3n_%
z86mkEEexAu&4X@Yww;t7@i$gb&fseZg}vdZ0qN*iF&1%yyn@IVFjm+<J~!5pX};~q
zFL%qsKLjlq_7UJh@Sr5@nK)-L>ca|FWV9}Lm63aC8g9cgTGuFJADkvQ4=)C{O8WvW
z|2Z%TbPD?NCuJ5PPwp1$%Uq4yE~Cx07{eY@`yHOj@4`#UGD__kzY5LV3+DREX1EoL
z^Jrt`jHBkHm2uq4`TLY;!8^8YUkgk!*8`w4EEUGS2Y8KrPiRfGA`YLgq%>`=-u>dt
zp=~iJw<?fjj#!M#kT@}pTxn=3mjgH%ytR+G0*?@-{RRCjS`$+G?y;3&;z86LgPTle
z;$@neLG9iFM$e_-Z)bw)T7~YOgwet&Zp4-f`@}Z9zD4$!{R_*4fwetY$Hp6D7Ub1f
zbu&@sf46t_!A)IP{yyo+l8mv0kwFB5pN+7A4T+qjjROvTwuShp3W7QmwhS==+U#zo
zrG>Qq!?RqWXKV-tH=)ESA9f%Kooot8`ViR;GbkjP&}7>ryQ?;|A#s2Sb|(`g*_dP}
ziT8Kzd(X0IW;5;dzl~?)ci+AD-OqE+IrrRi&!LqC$TjLSurtNr)QS%tP;c=v12>vE
z=a0?_7y~>*lFZdx3K(WNV8KtWv};qfipKjmA3C50{AO8#x&e-IxiX+NjX}=U0LrNx
zI3ULO#@YR6Yh+QYz|3EU@&00V{}%WliE0ivn|OT$nu&K4&`j`(b^$s7mr2xY$kR+b
zI|?qY8S{d?WL3e$l7Nowk#cAQFhEC>fR6W&<F9}Y0UHkBH?Dg3$;5dN+0;^5Qf~nj
z49vQz_r<>Q*XDxa6=B}pfB~{NKh66HXQ^f263IJqiT4S-Eke2z=Ne=;t~9k25JlDi
zrh6Yp+Beo^SZ!ZEa^ztLBP|~O{JjqP|IVPTH_$f)t*?zJ>Lk=M4tb`TrA(WU#J5us
zQxT4$w3T~GC!9r00Qr1~#aS`zKwd4JHsKA%pb=xWM&qot418Aw<*{1C*B)<29;;O`
z&N|94b`Q5qBnm=UwH3Zg90erdJ7qg1nQ#l*k%PAMRLq~?I&q@C4dX0$Mm&oI4@Ee9
z;z-D6gtAi%44U;@G$A{gE8r?8;k*jCIa_St$SgQa!iC_y{GrWkW<h{Uum*`7hdu$n
zMEa-V4C}qYY!T|g$|LSdNY=5oC_EOnfRhQvu(yY->3*?Wf#lzio$UG8kQNbc3`hfn
z8@n4P@K3;1E=DUwtjTW-KpHv`>67uK{dEN(#BN}Mju%k!1J;PZ@@WKL6TT<@(3}fc
znMpDqXV(sNb)bK^=ZHK)em*dj$(+INUJ@MHR8<LJ{Zem5%ZMUYX01}DHLgG@AyLYc
zM&HeR=sEF@q9hf*M-FspNT=9}tR44X9Jnn=HHutjo2J7yR+7Fzn_7*r*C0KkJZMuO
z*QWL*MvJIMBYmV_rDOX=IYzfAZIlya$$<l1k60~2|7U5T3l$%3&7Dt>4J}R0k~DQZ
zdvwn%=rs&uMDyW=Sh4W!vCX(sHtDJ7P!65BR6g}QLUiU*`P8ovqBEDur*uIvd>1MY
zoeT?Y#l7Es_cEk&6C4-$hoRDBvT-YE49GUMp-cAF^AE3h`sg+h-N1gxf}E8<gxz7<
z%P$~oBto?#Ayr@~Apy4VCt>}Jq|x0B4q6{TIpk+t!6}P@p}><LyA3x_+>l2&vBwdd
z+|J;ITVI9M|HzMCoQIwA4i*PD|3st43bDtgeUOk@r<Q6*tT5t<Pbxyo779*j9YWs#
zgi~9;gOQ(wC-y|hL;LoZL})TXFN+XKIS?nL7e-8MBo~!w#KlMAa$l0f(<p5nT1vXs
zW*e-U|6Vns^w?7waQHD^7~$$2R?ks>G1`D$i$0>SV`|K`-s&Tb#EpHV5^n6{q}1Xu
z<GV0d6GCh81&uG2iaN!9_r~$1-IP)4UtRaem$~u%4#lPDM9u84RrlYezbG5!OhQj2
zuJTHZu5<MU8|<GFlxs|@qY!E981|M7eL?uDsP6wd{4uRr1Ulm@wYTd>qu|77)%d<0
z->Kh+H}aq`-gjqwmwp6qbO(;o9>RSPpH6!8<9&<byP2m@(KnenJD}BlXJ3B3w`Uw;
zoY?KOLxN}e2SLr^yhYq&G*?1nC+rBq3JFGtB(l#w`le|2Y`hCjmn<nE{y9n)a!ktg
zywNwxgIdh}Q_iLf;T;RcsQgFIS*6Ed-vr-t`Vyfadp@MH=hULWP3nXvrcy4zBCR`0
z9XUS+uTzP=Ashb8DpgRQVrqp5jplX0rD2!M*a6&u=!J{|UNS-3;PoX{8B!R0?FvrX
zKc*z{y(mfaIW-wI{^fZ!$)~${_|PXr*9IlD{y?Pe%pa_hkos%tfoRnn>H~#{_CtEy
zqD!h*buWWjxX>Y3y08}~BGG2se(4oCw4AXnxjv``>Vvq^e18sB#F@|o`&oK>(xoXG
zEweMTEAtR;3*b}*=gw7JJ~?9%NxQl^G_~z7=<9HE!kgWNTNAS07UnqH-U%^Ifj%p3
z3-vH>MoZXFtpoS5IBf$)9pUt@6=9TwOb(j%SLoy_0DIVw65>p3ym1!Na-jy_koHeA
zh0t5t)onGy#ItY4Ng2ss9{?q<5jpRt5OUI28$~RA(*$Z*BX;)Kdx~`0S(3Dg^3s_I
z$(txlXCm+eBf@kh5}|OK<fNu_4l@c3gS3q=)ynBft>UT~nuFA-;4Ex-#)!KBpJIln
zO$dJ^VrL)}M9GAa%n;J8(-DGK+TZ?xav)55`6D8XJw4uq><)E+i=k12bUMi1SY6fr
zY-pjv5{nY;iSG^A08ge}XPOh5k<cb(dg7ec^e}5(1dGpK+x8iqr>*%NQtnX}Bu-Nb
z_K@czwc9?k=0-s1WN~uzH0nD{CsKHJi<o~iV+7=hm}iU_w6S(1*Dt>yPDR`xJiXq^
z+mW}_qQ4|3xlVhy($zC~Q}zfiM|~u_A60Ky1x>CmWaUNBbO;Kb+^exn`@oKL96V+I
zYR&WZJXxj__I%hid^6oyRLaXU_Na%e)r!nQRmuYOryE`KAeSPYjJnIa<<<3$f)#J@
z>O=|hPA|TQl6wG~Pr^p19koxcp6+88NV@v0XbXinLfs<nc{2|0uuL&$$le%d!@yzl
z!~B+CLrbd`+;0)!I)BaYJf~4EJTnz;#`wBmQwz5nuDQDZr~3Oo#=~@j2(nE`S}3G3
zAsN+ZhBd+ibUMiCZK&*0UcUo;t8!_2pYzdA9-U7d`C$7Se?p(dULCmw_Oy2Enj%7-
zkO(!ks%@=UyAEjMb>O!f5*}x4PHIDJNyc%kE5w=d^XD3W$ZDaTK~fGavQf=L{xbMu
zb>XZ&jdov;GkC9-(1HS9qTcH#|G~AK<cEB84xEsdT~k!~7kQcSs}x)*sgiB#LSLRL
zb;5c_Qa;gzdR>=h_SsLooszvV&SEoNkh4NxkI}A5J8PA;y@%@i=1bd73^=vnXl!^`
zeF8TdPjF}CDEALK>dwk;^usaaY~yLisu|4DmgF_+y{<gf>zaD4BZ_{af4ftAWt;(L
z>})yTjUIMHJGm6y%51F-=%Jk$0Ph`4y1pawvwwXj>k2bK7b|4X@K)ko#mJ`a9D#yL
z_&6sRsAK^~^Ya|;Le>r*K^#fa35qEV<st2P_?f63x*@H@7LKBZm3t<2)P+sj7}-Aj
zRtMe7@<zHrnK{z6LT_wI>XnRb*+llUfpM1h5AM@|8&2aMPyB_11GNoiK<UJ3lvq<a
zOp88KYf521wfp)Jjy;)1Tve&SQ`B0*SJc`O`j;l`Vea*DcbcQ`(6T`u&_C?U6zKi-
zlD1LeBI%J_GxU^t&<BAdGj8rolxt;K)R3L7mBaExMRpoSVTK5mAT&pWrh-=ij>Mk7
zTs%ob&j|U=J?3Ou4ahMGDaLsQX_*=48KehfoM%i#$iRt3h6cok`>gYc9_ZF;Wx|R?
zagJ{=<sr_4KaD6t`fEs3)KSto!g4oKdsFXEP<w<kF+uA&daV_HoGQYYwV}jvQQ}hg
zOOau(U`VW8&~O^LYZ7MmK;&LkMhmjmoTK$4RGfN3b0O$B#uj>+ExMvArY>MDW7vO1
zLC4j7LKkr1RmR#E)R(ye^@_G7vB=VJG4)VdK*!^Pj<*pN&+J~z?1wA}IvF5}4#>}6
zT@`;pZxD36P0;a5q8XXpL^WuCth<PkrynBBc&Y*GJe0PNq2&`SdNGQY+sDvyqTsOR
zg>Q*|+tE*=%b?#PEaY#b^@2D-!9`9%zmb!^Y667R2nn{J;DVN0^qXk8MZbxbTlAY~
zxuD-PstD7b81-3js+ENdT5dOKxoDN3<rK1LxgELw4_c0#e;wTx6h+W&`xnq{SgZP5
z=r$nleB`!Kber}t2Hhrj$_VOAG%G7YRS1FpqU{DnqmV(-W@EJrc*c0Chy`sX$juOP
zEM2XDDtC{e%2W@y0rLcrD0&ON>NdU_D5X@K+BaR84Gc<J7n_ljG)6$<AW5c>pmzv+
z8DS+*din;Gbhb&|S$Q32%R*R9Jmt9jNPj)}_o83=Qwzc>D15!=bagrIRE_M<%Nxn!
zH>mAZq}=L*?u8}sB5ilnLgiB}pr}+6{LaHNPA=Z!Z=iWpllELv`vU`omm2!ZY(B;g
z?kWmEGFKe#aa;ox_hPIFKQjyZae`L^sCTXT-8esRLv=ZF6DGU-t^TK5)z+Cf4^+T)
zY{pkx_7o5m2Gz>*o#68EYK&YpG(l=&bK<+OdmcoptgVkc&L?99I@ZDCAAC6f!K|@>
z?PCmh-QDQpo>eNxt?Gh2_!Zd5YggUQ6r{M;N?b}(`5xY%x+|ThZspSckCz<<XK9Xf
zHkLR8IR;rbF!xhgNk5aKnWi1rY%{$!m#&}58d8*QN*f)IyBdNsc*u`?<H(iC(;%Dg
zxvB1AfHmS)=wH;k{!8iwy&PRW>Lu#boj4<8OC#;&wp_i`dhlKD0nf#jen+}c{ha0X
z=MQ*rQdW4erB9B>W0fgetO9Kztz7|aWBVccUpTt|W7|M2;9^{I@uJqFEI-_YS=~@r
z;DzNf(k|_&YkU$ub1p`X4wqyc-R`=J%nMC92W}quF&jbIJ+OmjmgafYa^_gIjoH^8
zVba<SumEy`yM}hQs?dI6sB^MbNx5=$;%*o0)fE;Ti}H8wISbojw{g$%v&<2lFr421
zng)F|=%!_cKk1XT=7Ak4xqHf^7q9QYILP;W1b<EoSS?!Nh^`n;?*B8^U`c&dJLP}B
zPsX`lZ_0jn&HmR0S_ks3gO55i_27K8+cmf|-2oV_iN{m-W?|cQ^!yu~P_BK}YRbhJ
zvzL3nCXI!dOkNh&anHL49FbVk={>^Oke2qO3euj7?tVLWr<{$Cz^W4BX(T!%RbyV_
z5n~FCAvl|1bwM*jm^7}%%);V$tvX!b?0fpU>(K0jcct6;Z|cr6FY>qs@-lAq-U0>>
zP@cxa%+sp!(^xZ(_^z;uk*zN*h%Jd#r2cD2Hb;8=iB8O~p?hlKsfw_{y%ijz`nns7
z7_`)^o<lOtP!cN~e=I3dC-PeGT?)dZ^wq^X^w<$==&fT12D!ueNDy)di<hS~1+rZG
z>)%J)^Q~QY@%x++2bggR4sa%MWoc;tfGe}nzGeuwhH;yR<V4Tny8^12JkO&af=dIB
zN|XpZs)5@fpPmj1jlFGl8c}LIOAI=V&{Ts;BXm>7Zt!X*&*n$@2G2Ix<k=>fJR5Op
z2G2&En!&RXr)KbMgoO;AZ34=x{7}oukfBqu53MAbaqoULvwfc3#ef-a=9}h8(Ace0
z-D%r1UEbyV>&ZOGn%lBFA)Pox+zWV@f>AOE*>M@9&j#pqTD%A#*y1XPI}lt2wG&}W
zGC&-J#aU1ui?bjOLU0y>3lV&U;6emfk+E4jyO6@#&?DL-(!M=lhAkd};%RSB=k!({
zl1|LY+RPDw6-K0kLSC37qyr+9wt>b7nG$l59t)(`BricIWauuT1tx?N5A28aAj~f0
z1AYm8hrS5f_a4f4c=eO6YG^`v6RzTypz*!<RHcv=96NaaPoL4v1e`BDjGKr!H{!v>
z43Y^z&*eNUaRMTd%8`mu#(tpslvAWS30_BW9<<l^QqDuWVOQU(S{#J$1Q&3Leu8Tl
zvSa3}huVjBKxbErRX~g8=IXsTTbV)JoWMcmJvO|Lq4d`JG1eS$8=$_A5X7V8N9Y~n
zMJwTBqLC?|;NH!9Jle<!YvPQ-zhj(hXe`Aok4N+~5hY1H{M9y&aTSt+km_Y^Nx)iR
z;>=(SbxcQHhcC?GHB_gVYZ@8EoGb-a!EJC)iB5Cg&B?-wdHy*-cSndXIjqKdT^Htr
z4IZaNAJ*YXo^t2%;!WU_p+e*{&PYo1THV3x#^%dXnZ$`5R=21wb-hC62GN45y(N0L
zZWlTmqsmp~65=fiK_`Y)2!Xqf4}!9Oa9<x_!^KosFG>OqVAVl`$JuRZh7xUEccz?e
zFGp%s8J5PUaog(-HRzo*prxk5H+?Xfrz+k_+18X#I}6*zkN^bT=^e21b}4du(y7LR
zZfH-qQjWS_?<9;MX@yGgZujEwnoQoHTwmmUFtc}U`k1$`8hWIg`sAn#iZB=9ZV`5+
zDiQuvgq^9fwdvSi5zb3ZU7Ozi6A^Z#ir1#&{UR)<JZsZCszlhHa<5JAd{cyB`x7Ng
zBtO3L56cEVe?2V^<v}8{vA&5tXu{Lldb<)J=*hUU4xX%^;Cis0^@y10w_5xhb_ioX
z?OS{xxGu|n*cV!t-PYM(mzG!bG6i0n>-y$r98r}kYqJP{EwmZlFUt-FFxvJ|bWM9b
z=MSoqe}BE^3)I(j1u&~5A8?tRFiL6hs{!xtqxeq!f#OmdN`|8FV3$~!h<|Vw{1+;T
znFp_Y@PqzhaG6c`c0(a7r>6?rk|QM<^i3|l$QkYCMsUUqf)AXn0?r9~@cjr(Uh^Q0
zv?j2RN7|i6PLsaLI;T`nKhQU%e$7nvqIT~dm%d)4!cRqx`cVuh8nkMc&0vSaO{D(=
ztg^vTu;wcB7hfWrEwGNzuDbyzxqy>cZmp910eyQ|++6JuDW=>a<F)#R`slQm=uE{3
z#Wgf1AZg0=bAb9;OqzaKNKBBIkv<wEqT(*lK}nkvVc^M?)R2)A8gifW^6XxeVCi$I
zph5Kx<Vj%eK!e?@S3;NR6%*5JPCH?FOU_O~--&J-`kRvxGUy~pISe{Uw9}xIL^}nY
z%uY1vD{|0nNz3Q_$k~qJhkU)R!0Y(Umn&fH=jdCLF9-UjY7(pj+ync4iy)Jj51Ulb
zn}2Ho{CO`-Eiu~O+6Su}4Q4;yMELH5AxAGxjy*!Z4-!8ug4o;OYrJ8<5BU(Y+lQFh
z2W3YugS`-)tI-}e@(=I7zrI{GPlC2LBhO^=MsAe7s~Ybf@_D|Ww7uacTZ4@cVebR@
zZ|~^~w~qEnPIuj4xzm8yd9X}na8&b8Gy!JVad-@{`5Z6dF!AcuVfA>k?Nk^P3O)ff
z|H(?|25nQdF54++NC>M1tM#MdZNORZbhD_phc&`xvswgiH|obS=tw-$Q@4?%;h+Wb
zqTYhJz(OS7BnyMk#B(Zm7rG>n$8hW{3D1jj7V14HCB2WM8K+UhJzp8`*b(3z>umJ~
zrwi}ya3|gY-Jrfy9#%EpFC)E*H{;zIUT*U`-p9JU%JW3sz^x9*cSshqDCwto?95qB
zf`?RbQ}i6&P)WR>Xiel5zbtmW&>k7zd|lFBO!Oz-g}vlBuol??S9w0}-*^k=!lyCE
z9o<=sU9%@(V`fTnK-M(s749N7O-UwPxVzg)xp7h;zL}z;f1Qb0;!W|Z&@b;yEEaD}
zW?37)ZP%5vZrCtlYSV68*Z%rgi|Z8I$guZi*6f8j@PSr1|F}Z);gvB8Roi{~j77be
zooFXZ99?r&_UrFbU&EVGC;ADkSdKe#or!gcJ{ZL4vic%uw>l+>JCL1;c1`#YMNc@5
zKl%u+n{{FiU^Qtk`hyZ#VkXK{;J5P^RQt6K+^v(zQaN-y#MdFO^Q}k|Ctb9wg3D<_
zDO*s&2G6;~s|HkYe2-p`cM4ViURZIlfey?PN>Z1*Z2ti}--;As<NiI;B(#=9IVc0S
zW?<V4y+U5tTVuTVGGSfWdma2OOC~<B@C58Fyh42Ybr*RNNn94t0jL0UD1z5la3eGi
zqu-pkkDzi8He{SiSWt+L<^)g7gdL?jR=l!p7(1HbD}iNMX)elx?JKsC)(b2zZD7^m
zDy-Iukf)ca+jj%{xoz2Y@E-MSB5n@UGioVAE2|UjMz6QKPC6an6S2nbR1af~RbFZ6
zpNKXSlym(RvY@5jF542DG)Hzj)-<gD#8v1A+pwCbpA0ZczCHNK8vO(9ZnZ&!cMZ*<
zpRT*8*@{1cKx))idbsUfwW`^c_%6;cnf@tkk@(atAKMb2Vs``o3b-c=LsK=bgcSaP
zXIMXi`59i6?19hwE}LrGOgkUUFJQ8Yx9jn<1%f-duf(>f59;?X`k7kTEGHnB6s_WV
zjp#=ZcMDr+&FZhfpGyO?C0eNz8h0Hwln@f|38<>k-wBrjavNYL^Pt|O9aXEK%Xoy3
zZ_^^jSsvXhNP1H4(B`XB*L$ggg}s-g_J4)Vc{M3@y_141L@sr`OFhGiLfwM4SK}7&
z`s1^n>U&+ricwOZhMGXz%ltnvXZC)bpn@!z`HXhU{;uCAHtB)Y468=gPeZ4bC)Q$C
z+#~%u2&@0zM9Ii|360)r_$*1(0Dh8si)h0N_-Z+QsvK=mbSbnPI5g<BCDx0PK1eyB
zL-!u?*Qhpl!t!o+X-$ce#C@lv5llSK)J2<rJV|Xlehv_%0M5!WqM@<(Monn)X~|HK
z=bdyWUQK*&|6*ay4^&|He_yy2m>RZqV5hMiw|{02kxr)}FAQi)O`otcLkhz!Vp{*k
z%}wz=C<p27K%$Tb-z~5L!o`jVd5G%3PbAsr87&v@It@*TS-2A^rCOj3@ffgaP@fSg
zSM#_H_AS)Z-Ox|F?T>2Pi}-&0ge!aQiUygBbR#rLkL&m0_UFbCAKpcp9q)z0i+7Xh
z3B5<Pb-@$5-}K@Q95+F}l`RQH?R^dJ?+g5FRkZvqC0g6!uP^J|^7Br3JFniqIK<d(
zsL%3veoM#;i+c*m?!yM%yDK#V?YiTS{;0}adILC0uf8z~5A3=GSSf_Xv37kr{CfQP
z_^jj4VC7Aa?QBUZ|IpI^w847;l|r_h+K;Q6X+;Y5e1Apf1mq(Gr=zAF1@aC;{f0-2
z*I<Xn_Nq))owWC1WvK}eyP<F^Y{AY&4vhOQSXz43DP{q8t=n(LIFItVLFHQCj4fZ@
z!se!>M?d|-Ql8C~V%nK8>%F0j+o=rrN7?3^F}gi^E$r~*+Jw^dGh`Fy<$QA-x1v_F
zwR&k?Z;h+&YKt54uyJG4$y%7cO)Y!D_3*uCZ}@g+z<?;j9vS$QPhla&<Ro{!Eo`cc
zu`<Rl$=~92_4RL#dwB+GAII8a8^jGPf_Y#}I`>8h(9h4EBb(jhr7ImR+T-862)`(l
ze=<&ERfJ6FK!~iYHH)vve=ybA1I+ZKoir@qC3M%zi0K6M?`scYC4no7-w)~qPvT5X
z;WT)b#K2eb<ZnFOf-iVlR-|)9@UCjW+eTQCdHg)+Bi)%d<KPEQcpDloe>?tLBhGX4
zZ_lGnvdOeJqyTp*<9-ji>Ld(u@GW1E?;$L4Nb;%iz3b8wclOJ$mK%)|*F4^FCH@-n
zx^tr^)~e~D>tS#ZU;TYG0$+{5S0nJ%2z)gHUyZ>3*Aeid<2L+W_y%JSfbIB29b?T4
zjpx<|#@=3Hg!du62Ju_*44COOX3}GixudplC_ifd@T2^w{McjTqK<ILwIc7sk6bI9
zNL}GV>IyefSL7pg#W<v{EI{hY@km`+c>C?+R#Hh{{O2(L^1tNI>+_c=!8@vJ)KJsL
z`ybf6wYh}_W>!?rx_Ry`w+5@K@0vHi=I#ZxY?80Y>w=7gNj7|eZDCpYNSbJY=Nb0&
z({>RQ&yN`_ze5nS2T#QAxWL%3_+!j5%;4Zw44=B!C;eDLp>`=h&xnzj!&AT{r`JZ~
z>$WXrlEiwVZdC3<0nF*pY{=<!v>FeW@sN#&!+7Kw52x{P)59&JWTSwXU1ca>yOD}|
zsJOT!BJK2$?QXfq{!O+CGNXTD>scd0|H4Y_)hx(vW4FK+aTQb8_woBSi?BMjjJfPp
zhz~OVKf?4QehPj8{AS^IGk!t*?!d1azZ(2h{6hFG#xH_j6u(CNR&DyxmgmrK^~X&5
EU!&NiyZ`_I

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin b/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7.bin
new file mode 100755
index 0000000000000000000000000000000000000000..da534ee0a88337ba207fab8bbabb8fae7cc3d98e
GIT binary patch
literal 47032
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
M>=hK%zr&RO1eYWV$^ZZW

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin b/drivers/staging/mt7601u/mcu/bin/MT7601_formal_1.7_Debug.bin
new file mode 100755
index 0000000000000000000000000000000000000000..2cd32e72fc70c55d50b327195a6b17799ea78dc5
GIT binary patch
literal 51944
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
CnsToI

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/MT7650.bin b/drivers/staging/mt7601u/mcu/bin/MT7650.bin
new file mode 100755
index 0000000000000000000000000000000000000000..766aaba744e6e067aa18479812e2e06cc5968b53
GIT binary patch
literal 59580
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

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/RT85592.bin b/drivers/staging/mt7601u/mcu/bin/RT85592.bin
new file mode 100755
index 0000000000000000000000000000000000000000..cee5252de2ea770ebb94ef0c660ce668024cbba0
GIT binary patch
literal 35060
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
GNBjqO)p`8@

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/rt2860.bin b/drivers/staging/mt7601u/mcu/bin/rt2860.bin
new file mode 100755
index 0000000000000000000000000000000000000000..6d154837c026790d9e74a2cf3ed6456d374acdd7
GIT binary patch
literal 512
zcmbP`%D~9L<Lt)3Fd<b$Vg?YyXs{?F7sHY7|B*mnDWkLCe-(}Y|8*Gu|DQRtr{n*B
zuKx^BfTR%0gvmf?PN*nT156xK2V4YbJ_IZffUyYD?@?8hm(QHpk%o*><wtn{M_;Y2

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/rt2870.bin b/drivers/staging/mt7601u/mcu/bin/rt2870.bin
new file mode 100755
index 0000000000000000000000000000000000000000..875842add6eb3422b3843a716694154bd1a254aa
GIT binary patch
literal 8192
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
E17Xg7aR2}S

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin b/drivers/staging/mt7601u/mcu/bin/rt2870_wow.bin
new file mode 100755
index 0000000000000000000000000000000000000000..bfae0f0ab0e30fbf06a1e3a32cbe94238d0439f7
GIT binary patch
literal 12288
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
BP2~Up

literal 0
HcmV?d00001

diff --git a/drivers/staging/mt7601u/os/linux/rt_linux.c~ b/drivers/staging/mt7601u/os/linux/rt_linux.c~
new file mode 100755
index 0000000..49193e6
--- /dev/null
+++ b/drivers/staging/mt7601u/os/linux/rt_linux.c~
@@ -0,0 +1,6215 @@
+/****************************************************************************
+
+    Module Name:
+    UTIL/rt_linux.c
+
+    Abstract:
+	All functions provided from OS module are put here.
+
+	Note:
+	1. Can not use sizeof() for a structure with any parameter included
+	by any compile option, such as RTMP_ADAPTER.
+
+	Because the RTMP_ADAPTER size in the UTIL module is different with
+	DRIVER/NETIF.
+
+	2. Do not use any structure with any parameter included by PCI/USB/RBUS/
+	AP/STA.
+
+	Because the structure size in the UTIL module is different with
+	DRIVER/NETIF.
+
+	3. Do not use any structure defined in DRIVER module, EX: pAd.
+	So we can do module partition.
+
+	Revision History:
+	Who        When          What
+	---------  ----------    -------------------------------------------
+
+***************************************************************************/
+
+#define RTMP_MODULE_OS
+#define RTMP_MODULE_OS_UTIL
+
+
+#include "rtmp_comm.h"
+#include "rtmp_osabl.h"
+#include "rt_os_util.h"
+#include <linux/rtnetlink.h>
+
+#if defined(CONFIG_RA_HW_NAT) || defined(CONFIG_RA_HW_NAT_MODULE)
+#include "../../../../../../net/nat/hw_nat/ra_nat.h"
+#include "../../../../../../net/nat/hw_nat/frame_engine.h"
+#endif
+
+/* TODO */
+#undef RT_CONFIG_IF_OPMODE_ON_AP
+#undef RT_CONFIG_IF_OPMODE_ON_STA
+
+#if defined(CONFIG_AP_SUPPORT) && defined(CONFIG_STA_SUPPORT)
+#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode)	if (__OpMode == OPMODE_AP)
+#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode)	if (__OpMode == OPMODE_STA)
+#else
+#define RT_CONFIG_IF_OPMODE_ON_AP(__OpMode)
+#define RT_CONFIG_IF_OPMODE_ON_STA(__OpMode)
+#endif
+
+ULONG RTDebugLevel = RT_DEBUG_TRACE;
+ULONG RTDebugFunc = 0;
+
+#ifdef OS_ABL_FUNC_SUPPORT
+ULONG RTPktOffsetData = 0, RTPktOffsetLen = 0, RTPktOffsetCB = 0;
+#endif /* OS_ABL_FUNC_SUPPORT */
+
+#ifdef RTMP_RBUS_SUPPORT
+#if defined(CONFIG_RA_CLASSIFIER) || defined(CONFIG_RA_CLASSIFIER_MODULE)
+extern int (*ra_classifier_hook_rx) (struct sk_buff *skb, unsigned long cycle);
+extern volatile unsigned long classifier_cur_cycle;
+#endif /* CONFIG_RA_CLASSIFIER */
+#endif /* RTMP_RBUS_SUPPORT */
+
+#ifdef VENDOR_FEATURE4_SUPPORT
+ULONG OS_NumOfMemAlloc = 0, OS_NumOfMemFree = 0;
+#endif /* VENDOR_FEATURE4_SUPPORT */
+#ifdef VENDOR_FEATURE2_SUPPORT
+ULONG OS_NumOfPktAlloc = 0, OS_NumOfPktFree = 0;
+#endif /* VENDOR_FEATURE2_SUPPORT */
+
+/*
+ * the lock will not be used in TX/RX
+ * path so throughput should not be impacted
+ */
+BOOLEAN FlgIsUtilInit = FALSE;
+OS_NDIS_SPIN_LOCK UtilSemLock;
+
+#if 0				/* os abl move to os/linux/rt_profile.c */
+#ifdef SYSTEM_LOG_SUPPORT
+/* 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 */
+	/* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
+	"occurred replay counter different in Key Handshaking",
+	/* IW_RSNIE_DIFF_EVENT_FLAG */
+	"occurred RSNIE different in Key Handshaking",
+	/* IW_MIC_DIFF_EVENT_FLAG */
+	"occurred MIC different in Key Handshaking",
+	"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 */
+	/* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
+	"Pairwise Key Handshaking timeout",
+	"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 */
+	/* IW_STA_LINKDOWN_EVENT_FLAG */
+	"disconnects with our wireless client",
+	"scan completed",	/* IW_SCAN_COMPLETED_EVENT_FLAG */
+	/* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
+	"scan terminate!! Busy!! Enqueue fail!!",
+	"channel switch to ",	/* IW_CHANNEL_CHANGE_EVENT_FLAG */
+	"wireless mode is not support",	/* IW_STA_MODE_EVENT_FLAG */
+	/* IW_MAC_FILTER_LIST_EVENT_FLAG */
+	"blacklisted in MAC filter list",
+	/* IW_AUTH_REJECT_CHALLENGE_FAILURE */
+	"Authentication rejected because of challenge failure",
+	"Scanning",		/* IW_SCANNING_EVENT_FLAG */
+	"Start a new IBSS",	/* IW_START_IBSS_FLAG */
+	"Join the IBSS",	/* IW_JOIN_IBSS_FLAG */
+	"Shared WEP fail",	/* IW_SHARED_WEP_FAIL */
+};
+
+#ifdef IDS_SUPPORT
+/* for wireless IDS_spoof_attack event message */
+char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
+	"detected conflict SSID",	/* IW_CONFLICT_SSID_EVENT_FLAG */
+	/* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
+	"detected spoofed association response",
+	/* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
+	"detected spoofed reassociation responses",
+	/* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
+	"detected spoofed probe response",
+	"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 */
+	/* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
+	"detected spoofed unknown management frame",
+	"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 */
+	/* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
+	"detected association request flooding",
+	/* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
+	"detected reassociation request flooding",
+	"detected probe request flooding", /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
+	/* IW_FLOOD_DISASSOC_EVENT_FLAG */
+	"detected disassociation flooding",
+	/* IW_FLOOD_DEAUTH_EVENT_FLAG */
+	"detected deauthentication flooding",
+	/* IW_FLOOD_EAP_REQ_EVENT_FLAG */
+	"detected 802.1x eap-request flooding"
+};
+#endif /* IDS_SUPPORT */
+
+#ifdef WSC_INCLUDED
+/* for WSC wireless event message */
+char const *pWirelessWscEventText[IW_WSC_EVENT_TYPE_NUM] = {
+	"PBC Session Overlap",	/* IW_WSC_PBC_SESSION_OVERLAP */
+	/* IW_WSC_REGISTRAR_SUPPORT_PBC */
+	"This WPS Registrar supports PBC",
+	/* IW_WSC_REGISTRAR_SUPPORT_PIN */
+	"This WPS Registrar supports PIN",
+	"WPS status success",	/* IW_WSC_STATUS_SUCCESS */
+	"WPS status fail",	/* IW_WSC_STATUS_FAIL */
+	"WPS 2 mins time out!",	/* IW_WSC_2MINS_TIMEOUT */
+	"WPS Send EAPOL_Start!",	/* IW_WSC_SEND_EAPOL_START */
+	"WPS Send WscStart!",	/* IW_WSC_SEND_WSC_START */
+	"WPS Send M1!",		/* IW_WSC_SEND_M1 */
+	"WPS Send M2!",		/* IW_WSC_SEND_M2 */
+	"WPS Send M3!",		/* IW_WSC_SEND_M3 */
+	"WPS Send M4!",		/* IW_WSC_SEND_M4 */
+	"WPS Send M5!",		/* IW_WSC_SEND_M5 */
+	"WPS Send M6!",		/* IW_WSC_SEND_M6 */
+	"WPS Send M7!",		/* IW_WSC_SEND_M7 */
+	"WPS Send M8!",		/* IW_WSC_SEND_M8 */
+	"WPS Send WscDone!",	/* IW_WSC_SEND_DONE */
+	"WPS Send WscAck!",	/* IW_WSC_SEND_ACK */
+	"WPS Send WscNack!",	/* IW_WSC_SEND_NACK */
+	"WPS Receive WscStart!",	/* IW_WSC_RECEIVE_WSC_START */
+	"WPS Receive M1!",	/* IW_WSC_RECEIVE_M1 */
+	"WPS Receive M2!",	/* IW_WSC_RECEIVE_M2 */
+	"WPS Receive M3!",	/* IW_WSC_RECEIVE_M3 */
+	"WPS Receive M4!",	/* IW_WSC_RECEIVE_M4 */
+	"WPS Receive M5!",	/* IW_WSC_RECEIVE_M5 */
+	"WPS Receive M6!",	/* IW_WSC_RECEIVE_M6 */
+	"WPS Receive M7!",	/* IW_WSC_RECEIVE_M7 */
+	"WPS Receive M8!",	/* IW_WSC_RECEIVE_M8 */
+	"WPS Receive WscDone!",	/* IW_WSC_RECEIVE_DONE */
+	"WPS Receive WscAck!",	/* IW_WSC_RECEIVE_ACK */
+	"WPS Receive WscNack!",	/* IW_WSC_RECEIVE_NACK */
+	"Not only one candidate found"	/* IW_WSC_MANY_CANDIDATE */
+};
+#endif /* WSC_INCLUDED */
+
+#ifdef CONFIG_STA_SUPPORT
+#ifdef IWSC_SUPPORT
+/* for IWSC wireless event message */
+char const *pWirelessIWscEventText[IW_IWSC_EVENT_TYPE_NUM] = {   	
+	"IWSC - T1 mins time out!",									/* IW_IWSC_T1_TIMER_TIMEOUT */
+	"IWSC - T2 mins time out!",									/* IW_IWSC_T2_TIMER_TIMEOUT */
+	"IWSC - Become Registrar",									/* IW_IWSC_BECOME_REGISTRAR */
+	"IWSC - Become Enrollee",									/* IW_IWSC_BECOME_ENROLLEE */
+	"IWSC - Entry time out",									/* IW_IWSC_ENTRY_TIMER_TIMEOUT */
+	};
+#endif /* IWSC_SUPPORT */
+#endif /* CONFIG_STA_SUPPORT */
+#endif /* SYSTEM_LOG_SUPPORT */
+#endif /* 0 */
+
+BOOLEAN RTMP_OS_Alloc_RscOnly(VOID *pRscSrc, UINT32 RscLen);
+BOOLEAN RTMP_OS_Remove_Rsc(LIST_HEADER *pRscList, VOID *pRscSrc);
+
+/*
+========================================================================
+Routine Description:
+	Initialize something in UTIL module.
+
+Arguments:
+	None
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpUtilInit(VOID)
+{
+	if (FlgIsUtilInit == FALSE) {
+		OS_NdisAllocateSpinLock(&UtilSemLock);
+		FlgIsUtilInit = TRUE;
+	}
+}
+
+/* timeout -- ms */
+static inline VOID __RTMP_SetPeriodicTimer(
+	IN OS_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 */
+static inline VOID __RTMP_OS_Init_Timer(
+	IN VOID *pReserved,
+	IN OS_NDIS_MINIPORT_TIMER * pTimer,
+	IN TIMER_FUNCTION function,
+	IN PVOID data)
+{
+	if (!timer_pending(pTimer)) {
+		init_timer(pTimer);
+		pTimer->data = (unsigned long)data;
+		pTimer->function = function;
+	}
+}
+
+static inline VOID __RTMP_OS_Add_Timer(
+	IN OS_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);
+}
+
+static inline VOID __RTMP_OS_Mod_Timer(
+	IN OS_NDIS_MINIPORT_TIMER * pTimer,
+	IN unsigned long timeout)
+{
+	timeout = ((timeout * OS_HZ) / 1000);
+	mod_timer(pTimer, jiffies + timeout);
+}
+
+static inline VOID __RTMP_OS_Del_Timer(
+	IN OS_NDIS_MINIPORT_TIMER * pTimer,
+	OUT BOOLEAN *pCancelled)
+{
+	if (timer_pending(pTimer))
+		*pCancelled = del_timer_sync(pTimer);
+	else
+		*pCancelled = TRUE;
+}
+
+static inline VOID __RTMP_OS_Release_Timer(
+	IN OS_NDIS_MINIPORT_TIMER * pTimer)
+{
+	/* nothing to do */
+}
+
+#if 0
+VOID RTMP_OS_Release_Packet(
+	IN PRTMP_ADAPTER pAd,
+	IN PQUEUE_ENTRY pEntry)
+{
+	/*RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry); */
+}
+#endif /* Unused */
+
+/* Unify all delay routine by using udelay */
+VOID RTMPusecDelay(ULONG usec)
+{
+	ULONG i;
+
+	for (i = 0; i < (usec / 50); i++)
+		udelay(50);
+
+	if (usec % 50)
+		udelay(usec % 50);
+}
+
+
+/* Unify all delay routine by using udelay */
+VOID RtmpOsUsDelay(ULONG value)
+{
+	ULONG i;
+
+	udelay(value);
+}
+
+VOID RtmpOsMsDelay(ULONG msec)
+{
+	mdelay(msec);
+}
+
+void RTMP_GetCurrentSystemTime(LARGE_INTEGER * time)
+{
+	time->u.LowPart = jiffies;
+}
+
+void RTMP_GetCurrentSystemTick(ULONG *pNow)
+{
+	*pNow = jiffies;
+}
+
+/* pAd MUST allow to be NULL */
+
+NDIS_STATUS os_alloc_mem(
+	IN VOID *pReserved,
+	OUT UCHAR **mem,
+	IN ULONG size)
+{
+	*mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
+	if (*mem) {
+#ifdef VENDOR_FEATURE4_SUPPORT
+		OS_NumOfMemAlloc++;
+#endif /* VENDOR_FEATURE4_SUPPORT */
+
+		return NDIS_STATUS_SUCCESS;
+	} else
+		return NDIS_STATUS_FAILURE;
+}
+
+NDIS_STATUS os_alloc_mem_suspend(
+	IN VOID *pReserved,
+	OUT UCHAR **mem,
+	IN ULONG size)
+{
+	*mem = (PUCHAR) kmalloc(size, GFP_KERNEL);
+	if (*mem) {
+#ifdef VENDOR_FEATURE4_SUPPORT
+		OS_NumOfMemAlloc++;
+#endif /* VENDOR_FEATURE4_SUPPORT */
+
+		return NDIS_STATUS_SUCCESS;
+	} else
+		return NDIS_STATUS_FAILURE;
+}
+
+/* pAd MUST allow to be NULL */
+NDIS_STATUS os_free_mem(
+	IN VOID *pReserved,
+	IN PVOID mem)
+{
+	ASSERT(mem);
+	kfree(mem);
+
+#ifdef VENDOR_FEATURE4_SUPPORT
+	OS_NumOfMemFree++;
+#endif /* VENDOR_FEATURE4_SUPPORT */
+
+	return NDIS_STATUS_SUCCESS;
+}
+
+#if defined(RTMP_RBUS_SUPPORT) || defined (RTMP_FLASH_SUPPORT)
+/* The flag "CONFIG_RALINK_FLASH_API" is used for APSoC Linux SDK */
+#ifdef CONFIG_RALINK_FLASH_API
+
+int32_t FlashRead(
+	uint32_t *dst,
+	uint32_t *src,
+	uint32_t count);
+
+int32_t FlashWrite(
+	uint16_t *source,
+	uint16_t *destination,
+	uint32_t numBytes);
+#else /* CONFIG_RALINK_FLASH_API */
+
+#ifdef RA_MTD_RW_BY_NUM
+#if defined (CONFIG_RT2880_FLASH_32M)
+#define MTD_NUM_FACTORY 5
+#else
+#define MTD_NUM_FACTORY 2
+#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);
+#else
+extern int ra_mtd_write_nm(char *name, loff_t to, size_t len, const u_char *buf);
+extern int ra_mtd_read_nm(char *name, loff_t from, size_t len, u_char *buf);
+#endif
+
+#endif /* CONFIG_RALINK_FLASH_API */
+
+void RtmpFlashRead(
+	UCHAR *p,
+	ULONG a,
+	ULONG b)
+{
+#ifdef CONFIG_RALINK_FLASH_API
+	FlashRead((uint32_t *) p, (uint32_t *) a, (uint32_t) b);
+#else
+#ifdef RA_MTD_RW_BY_NUM
+	ra_mtd_read(MTD_NUM_FACTORY, 0, (size_t) b, p);
+#else
+	ra_mtd_read_nm("Factory", a&0xFFFF, (size_t) b, p);
+#endif
+#endif /* CONFIG_RALINK_FLASH_API */
+}
+
+void RtmpFlashWrite(
+	UCHAR * p,
+	ULONG a,
+	ULONG b)
+{
+#ifdef CONFIG_RALINK_FLASH_API
+	FlashWrite((uint16_t *) p, (uint16_t *) a, (uint32_t) b);
+#else
+#ifdef RA_MTD_RW_BY_NUM
+	ra_mtd_write(MTD_NUM_FACTORY, 0, (size_t) b, p);
+#else
+	ra_mtd_write_nm("Factory", a&0xFFFF, (size_t) b, p);
+#endif
+#endif /* CONFIG_RALINK_FLASH_API */
+}
+#endif /* defined(RTMP_RBUS_SUPPORT) || defined (RTMP_FLASH_SUPPORT) */
+
+
+PNDIS_PACKET RtmpOSNetPktAlloc(VOID *dummy, int size)
+{
+	struct sk_buff *skb;
+	/* Add 2 more bytes for ip header alignment */
+	skb = dev_alloc_skb(size + 2);
+	if (skb != NULL)
+		MEM_DBG_PKT_ALLOC_INC(skb);
+
+	return ((PNDIS_PACKET) skb);
+}
+
+PNDIS_PACKET RTMP_AllocateFragPacketBuffer(VOID *dummy, ULONG len)
+{
+	struct sk_buff *pkt;
+
+	pkt = dev_alloc_skb(len);
+
+	if (pkt == NULL) {
+		DBGPRINT(RT_DEBUG_ERROR,
+			 ("can't allocate frag rx %ld size packet\n", len));
+	}
+
+	if (pkt) {
+		MEM_DBG_PKT_ALLOC_INC(pkt);
+		RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+	}
+
+	return (PNDIS_PACKET) pkt;
+}
+
+#if 0 /* os abl move to os/linux/rt_profile.c */
+VOID RTMPFreeAdapter(
+	IN PRTMP_ADAPTER pAd)
+{
+	POS_COOKIE os_cookie;
+	int index;
+
+	os_cookie = (POS_COOKIE) pAd->OS_Cookie;
+
+	if (pAd->BeaconBuf)
+		os_free_mem(NULL, pAd->BeaconBuf);
+
+	NdisFreeSpinLock(&pAd->MgmtRingLock);
+
+#ifdef RTMP_MAC_PCI
+	NdisFreeSpinLock(&pAd->RxRingLock);
+#if defined(RT3090) || defined(RT3592) || defined(RT3390) || defined(RT3593)
+	NdisFreeSpinLock(&pAd->McuCmdLock);
+#endif /* defined(RT3090) || defined(RT3592) || defined(RT3390) || defined(RT3593) */
+#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);
+	NdisFreeSpinLock(&pAd->TimerSemLock);
+
+#ifdef CONFIG_AP_SUPPORT
+#ifdef UAPSD_SUPPORT
+	NdisFreeSpinLock(&pAd->UAPSDEOSPLock);	/* OS_ABL_SUPPORT */
+#endif /* UAPSD_SUPPORT */
+#endif /* CONFIG_AP_SUPPORT */
+
+	if (os_cookie)
+		os_free_mem(NULL, os_cookie);
+
+	{
+#ifdef VENDOR_FEATURE4_SUPPORT
+		extern ULONG OS_NumOfMemAlloc, OS_NumOfMemFree;
+		printk(KERN_ERR "OS_NumOfMemAlloc = %ld, OS_NumOfMemFree = %ld\n",
+		       OS_NumOfMemAlloc, OS_NumOfMemFree);
+#endif /* VENDOR_FEATURE4_SUPPORT */
+#ifdef VENDOR_FEATURE2_SUPPORT
+		printk(KERN_ERR "Number of Packet Allocated = %d\n"
+				, pAd->NumOfPktAlloc);
+		printk(KERN_ERR "Number of Packet Freed = %d\n"
+				, pAd->NumOfPktFree);
+#endif /* VENDOR_FEATURE2_SUPPORT */
+	}
+
+	/*
+	 * pci_free_consistent(os_cookie->pci_dev,
+	 * sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
+	 */
+	vfree(pAd);
+}
+#endif /* 0 */
+
+#if 0
+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);
+}
+
+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) {
+		MEM_DBG_PKT_ALLOC_INC(pkt);
+		RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
+		*VirtualAddress = (PVOID) pkt->data;
+	} else {
+		*VirtualAddress = (PVOID) NULL;
+	}
+
+	return (PNDIS_PACKET) pkt;
+}
+
+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;
+
+	MEM_DBG_PKT_ALLOC_INC(pkt);
+	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(KERN_ERR "###Clone###\n");
+
+	return NDIS_STATUS_SUCCESS;
+}
+#endif /* Unused */
+
+/*
+	The allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
+*/
+NDIS_STATUS RTMPAllocateNdisPacket(
+	IN VOID *pReserved,
+	OUT PNDIS_PACKET *ppPacket,
+	IN UCHAR *pHeader,
+	IN UINT HeaderLen,
+	IN UCHAR *pData,
+	IN UINT DataLen)
+{
+	struct sk_buff *pPacket;
+
+
+	ASSERT(pData);
+	ASSERT(DataLen);
+
+	pPacket = dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING);
+	if (pPacket == NULL) {
+		*ppPacket = NULL;
+#ifdef DEBUG
+		printk(KERN_ERR "RTMPAllocateNdisPacket Fail\n\n");
+#endif
+		return NDIS_STATUS_FAILURE;
+	}
+	MEM_DBG_PKT_ALLOC_INC(pPacket);
+
+	/* Clone the frame content and update the length of packet */
+	if (HeaderLen > 0)
+		NdisMoveMemory(pPacket->data, pHeader, HeaderLen);
+	if (DataLen > 0)
+		NdisMoveMemory(pPacket->data + HeaderLen, pData, DataLen);
+	skb_put(pPacket, HeaderLen + DataLen);
+/* printk(KERN_ERR "%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));*/
+
+	RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
+	*ppPacket = (PNDIS_PACKET)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 VOID *pReserved,
+	IN PNDIS_PACKET pPacket)
+{
+	dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
+	MEM_DBG_PKT_FREE_INC(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 *info,
+	OUT UCHAR **pSrcBufVA,
+	OUT UINT *pSrcBufLen)
+{
+	info->BufferCount = 1;
+	info->pFirstBuffer = (PNDIS_BUFFER) GET_OS_PKT_DATAPTR(pPacket);
+	info->PhysicalBufferCount = 1;
+	info->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
+
+	*pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
+	*pSrcBufLen = GET_OS_PKT_LEN(pPacket);
+
+#ifdef TX_PKT_SG
+	if (RTMP_GET_PKT_SG(pPacket)) {
+		struct sk_buff *skb = (struct sk_buff *)pPacket;
+		int i, nr_frags = skb_shinfo(skb)->nr_frags;
+		
+		info->BufferCount =  nr_frags + 1;
+		info->PhysicalBufferCount = info->BufferCount;
+		info->sg_list[0].data = (VOID *)GET_OS_PKT_DATAPTR(pPacket);
+		info->sg_list[0].len = skb_headlen(skb);
+		for (i = 0; i < nr_frags; i++) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+			
+			info->sg_list[i+1].data = ((void *) page_address(frag->page) +
+									frag->page_offset);
+			info->sg_list[i+1].len = frag->size;
+		}
+	}
+#endif /* TX_PKT_SG */
+}
+
+
+#if 0
+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;
+	}
+}
+#endif /* Unused */
+
+
+PNDIS_PACKET DuplicatePacket(
+	IN PNET_DEV pNetDev,
+	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) {
+		MEM_DBG_PKT_ALLOC_INC(skb);
+		skb->dev = pNetDev;	/*get_netdev_from_bssid(pAd, FromWhichBSSID); */
+		pRetPacket = OSPKT_TO_RTPKT(skb);
+	}
+#if 0
+	if ((skb = __dev_alloc_skb(DataSize + 2 + 32, MEM_ALLOC_FLAG)) != NULL) {
+		skb_reserve(skb, 2 + 32);
+		NdisMoveMemory(skb->tail, pData, DataSize);
+		skb_put(skb, DataSize);
+		skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
+		pRetPacket = OSPKT_TO_RTPKT(skb);
+	}
+#endif
+
+	return pRetPacket;
+
+}
+
+
+PNDIS_PACKET duplicate_pkt(
+	IN PNET_DEV pNetDev,
+	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) {
+		MEM_DBG_PKT_ALLOC_INC(skb);
+
+		skb_reserve(skb, 2);
+		NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
+		skb_put(skb, HdrLen);
+		NdisMoveMemory(skb->tail, pData, DataSize);
+		skb_put(skb, DataSize);
+		skb->dev = pNetDev;	/*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 VOID *pReserved,
+	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);
+		MEM_DBG_PKT_FREE_INC(skb);
+
+		if (newskb == NULL) {
+			DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
+			return NULL;
+		}
+		skb = newskb;
+		MEM_DBG_PKT_ALLOC_INC(skb);
+	}
+
+	return OSPKT_TO_RTPKT(skb);
+
+#if 0
+	if ((data = skb_put(skb, TKIP_TX_MIC_SIZE)) != NULL) {	/* If we can extend it, well, copy it first. */
+		NdisMoveMemory(data, pAd->PrivateInfo.Tx.MIC, TKIP_TX_MIC_SIZE);
+	} else {
+		/* Otherwise, copy the packet. */
+		newskb =
+		    skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE,
+				    GFP_ATOMIC);
+		dev_kfree_skb_any(skb);
+		MEM_DBG_PKT_FREE_INC(skb);
+
+		if (newskb == NULL) {
+			DBGPRINT(RT_DEBUG_ERROR,
+				 ("Extend Tx.MIC to packet failed!, dropping packet\n"));
+			return NULL;
+		}
+		skb = newskb;
+		MEM_DBG_PKT_ALLOC_INC(skb);
+
+		NdisMoveMemory(skb->tail, pAd->PrivateInfo.Tx.MIC,
+			       TKIP_TX_MIC_SIZE);
+		skb_put(skb, TKIP_TX_MIC_SIZE);
+	}
+
+	return OSPKT_TO_RTPKT(skb);
+#endif
+
+}
+
+#ifdef CONFIG_AP_SUPPORT
+PNDIS_PACKET duplicate_pkt_with_VLAN(
+	IN PNET_DEV pNetDev,
+	IN USHORT VLAN_VID,
+	IN USHORT VLAN_Priority,
+	IN PUCHAR pHeader802_3,
+	IN UINT HdrLen,
+	IN PUCHAR pData,
+	IN ULONG DataSize,
+	IN UCHAR FromWhichBSSID,
+	IN UCHAR *TPID)
+{
+	struct sk_buff *skb;
+	PNDIS_PACKET pPacket = NULL;
+	UINT16 VLAN_Size;
+
+	if ((skb = __dev_alloc_skb(HdrLen + DataSize + LENGTH_802_1Q + 2,
+				   MEM_ALLOC_FLAG)) != NULL) {
+		MEM_DBG_PKT_ALLOC_INC(skb);
+
+		skb_reserve(skb, 2);
+
+		/* copy header (maybe +VLAN tag) */
+		VLAN_Size = VLAN_8023_Header_Copy(VLAN_VID, VLAN_Priority,
+						  pHeader802_3, HdrLen,
+						  skb->tail, FromWhichBSSID,
+						  TPID);
+		skb_put(skb, HdrLen + VLAN_Size);
+
+		/* copy data body */
+		NdisMoveMemory(skb->tail, pData, DataSize);
+		skb_put(skb, DataSize);
+		skb->dev = pNetDev;	/*get_netdev_from_bssid(pAd, FromWhichBSSID); */
+		pPacket = OSPKT_TO_RTPKT(skb);
+	}
+
+	return pPacket;
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+/*
+	========================================================================
+
+	Routine Description:
+		Send a L2 frame to upper daemon to trigger state machine
+
+	Arguments:
+		pAd - pointer to our pAdapter context
+
+	Return Value:
+
+	Note:
+
+	========================================================================
+*/
+BOOLEAN RTMPL2FrameTxAction(
+	IN VOID * pCtrlBkPtr,
+	IN PNET_DEV pNetDev,
+	IN RTMP_CB_8023_PACKET_ANNOUNCE _announce_802_3_packet,
+	IN UCHAR apidx,
+	IN PUCHAR pData,
+	IN UINT32 data_len,
+	IN	UCHAR			OpMode)
+{
+	struct sk_buff *skb = dev_alloc_skb(data_len + 2);
+
+	if (!skb) {
+		DBGPRINT(RT_DEBUG_ERROR,
+			 ("%s : Error! Can't allocate a skb.\n", __FUNCTION__));
+		return FALSE;
+	}
+
+	MEM_DBG_PKT_ALLOC_INC(skb);
+	/*get_netdev_from_bssid(pAd, apidx)); */
+	SET_OS_PKT_NETDEV(skb, pNetDev);
+
+	/* 16 byte align the IP header */
+	skb_reserve(skb, 2);
+
+	/* Insert the frame content */
+	NdisMoveMemory(GET_OS_PKT_DATAPTR(skb), pData, data_len);
+
+	/* End this frame */
+	skb_put(GET_OS_PKT_TYPE(skb), data_len);
+
+	DBGPRINT(RT_DEBUG_TRACE, ("%s doen\n", __FUNCTION__));
+
+	_announce_802_3_packet(pCtrlBkPtr, skb, OpMode);
+
+	return TRUE;
+
+}
+
+
+PNDIS_PACKET ExpandPacket(
+	IN VOID *pReserved,
+	IN PNDIS_PACKET pPacket,
+	IN UINT32 ext_head_len,
+	IN UINT32 ext_tail_len)
+{
+	struct sk_buff *skb, *newskb;
+
+	skb = RTPKT_TO_OSPKT(pPacket);
+	if (skb_cloned(skb) || (skb_headroom(skb) < ext_head_len)
+	    || (skb_tailroom(skb) < ext_tail_len)) {
+		UINT32 head_len =
+		    (skb_headroom(skb) <
+		     ext_head_len) ? ext_head_len : skb_headroom(skb);
+		UINT32 tail_len =
+		    (skb_tailroom(skb) <
+		     ext_tail_len) ? ext_tail_len : skb_tailroom(skb);
+
+		/* alloc a new skb and copy the packet */
+		newskb = skb_copy_expand(skb, head_len, tail_len, GFP_ATOMIC);
+
+		dev_kfree_skb_any(skb);
+		MEM_DBG_PKT_FREE_INC(skb);
+
+		if (newskb == NULL) {
+			DBGPRINT(RT_DEBUG_ERROR,
+				 ("Extend Tx buffer for WPI failed!, dropping packet!\n"));
+			return NULL;
+		}
+		skb = newskb;
+		MEM_DBG_PKT_ALLOC_INC(skb);
+	}
+
+	return OSPKT_TO_RTPKT(skb);
+
+}
+
+PNDIS_PACKET ClonePacket(
+	IN VOID *pReserved,
+	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 */
+		MEM_DBG_PKT_ALLOC_INC(pClonedPkt);
+		pClonedPkt->dev = pRxPkt->dev;
+		pClonedPkt->data = pData;
+		pClonedPkt->len = DataSize;
+		pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
+		ASSERT(DataSize < 1530);
+	}
+	return pClonedPkt;
+}
+
+VOID RtmpOsPktInit(
+	IN PNDIS_PACKET pNetPkt,
+	IN PNET_DEV pNetDev,
+	IN UCHAR *pData,
+	IN USHORT DataSize)
+{
+	PNDIS_PACKET pRxPkt;
+
+	pRxPkt = RTPKT_TO_OSPKT(pNetPkt);
+
+	SET_OS_PKT_NETDEV(pRxPkt, pNetDev);
+	SET_OS_PKT_DATAPTR(pRxPkt, pData);
+	SET_OS_PKT_LEN(pRxPkt, DataSize);
+	SET_OS_PKT_DATATAIL(pRxPkt, pData, DataSize);
+}
+
+
+void wlan_802_11_to_802_3_packet(
+	IN PNET_DEV pNetDev,
+	IN UCHAR OpMode,
+	IN USHORT VLAN_VID,
+	IN USHORT VLAN_Priority,
+	IN PNDIS_PACKET pRxPacket,
+	IN UCHAR *pData,
+	IN ULONG DataSize,
+	IN PUCHAR pHeader802_3,
+	IN UCHAR FromWhichBSSID,
+	IN UCHAR *TPID)
+{
+	struct sk_buff *pOSPkt;
+
+	ASSERT(pHeader802_3);
+
+	pOSPkt = RTPKT_TO_OSPKT(pRxPacket);
+
+	/*get_netdev_from_bssid(pAd, FromWhichBSSID); */
+	pOSPkt->dev = pNetDev;
+	pOSPkt->data = pData;
+	pOSPkt->len = DataSize;
+	pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+
+	/* copy 802.3 header */
+#ifdef CONFIG_AP_SUPPORT
+	RT_CONFIG_IF_OPMODE_ON_AP(OpMode)
+	{
+		/* maybe insert VLAN tag to the received packet */
+		UCHAR VLAN_Size = 0;
+		UCHAR *data_p;
+
+		if (VLAN_VID != 0)
+			VLAN_Size = LENGTH_802_1Q;
+
+		data_p = skb_push(pOSPkt, LENGTH_802_3 + VLAN_Size);
+
+		VLAN_8023_Header_Copy(VLAN_VID, VLAN_Priority,
+				      pHeader802_3, LENGTH_802_3,
+				      data_p, FromWhichBSSID, TPID);
+	}
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_STA_SUPPORT
+	RT_CONFIG_IF_OPMODE_ON_STA(OpMode)
+	{
+	    NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
+	}
+#endif /* CONFIG_STA_SUPPORT */
+
+}
+
+
+#ifdef HDR_TRANS_SUPPORT
+VOID RtmpOsSetPacket(
+	IN PNET_DEV pNetDev,
+	IN PNDIS_PACKET pRxPacket,
+	IN UCHAR *pData,
+	IN ULONG DataSize)
+{
+
+	struct sk_buff *pOSPkt;
+
+	pOSPkt = RTPKT_TO_OSPKT(pRxPacket);
+
+	pOSPkt->dev = pNetDev;
+	pOSPkt->data = pData;
+	pOSPkt->len = DataSize;
+	pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+}
+
+#endif /* HDR_TRANS_SUPPORT */
+
+
+void hex_dump(char *str, UCHAR *pSrcBufVA, UINT SrcBufLen)
+{
+#ifdef DBG
+	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 < SrcBufLen; x++) {
+		if (x % 16 == 0)
+			printk("0x%04x : ", x);
+		printk("%02x ", ((unsigned char)pt[x]));
+		if (x % 16 == 15)
+			printk("\n");
+	}
+	printk("\n");
+#endif /* DBG */
+}
+
+#ifdef SYSTEM_LOG_SUPPORT
+/*
+	========================================================================
+
+	Routine Description:
+		Send log message through wireless event
+
+		Support standard iw_event with IWEVCUSTOM. It is used below.
+
+		iwreq_data.data.flags is used to store event_flag that is
+		defined by user. iwreq_data.data.length is the length of the
+		event log.
+
+		The format of the event log is composed of the entry's MAC
+		address and the desired log message (refer to
+		pWirelessEventText).
+
+			ex: 11:22:33:44:55:66 has associated successfully
+
+		p.s. The requirement of Wireless Extension is v15 or newer.
+
+	========================================================================
+*/
+VOID RtmpOsSendWirelessEvent(
+	IN VOID *pAd,
+	IN USHORT Event_flag,
+	IN PUCHAR pAddr,
+	IN UCHAR BssIdx,
+	IN CHAR Rssi,
+	IN RTMP_OS_SEND_WLAN_EVENT pFunc)
+{
+#if WIRELESS_EXT >= 15
+	pFunc(pAd, Event_flag, pAddr, BssIdx, Rssi);
+#else
+	DBGPRINT(RT_DEBUG_ERROR,
+		 ("%s : The Wireless Extension MUST be v15 or newer.\n",
+		  __FUNCTION__));
+#endif /* WIRELESS_EXT >= 15 */
+}
+#endif /* SYSTEM_LOG_SUPPORT */
+
+#ifdef CONFIG_AP_SUPPORT
+VOID SendSignalToDaemon(
+	IN INT sig,
+	RTMP_OS_PID pid,
+	unsigned long pid_no)
+{
+#if 0
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+	if (pid == NULL) {
+		DBGPRINT(RT_DEBUG_TRACE, ("SignalError:Pid is NULL!\n"));
+		return;
+	}
+
+	if (pid_no != GET_PID_NUMBER(pid)) {
+		DBGPRINT(RT_DEBUG_TRACE,
+			 ("SignalError:pid_no(%ld) != pid_nr(%d)\n", pid_no,
+			  GET_PID_NUMBER(pid)));
+		return;
+	}
+#endif
+	CHECK_PID_LEGALITY(pid) {
+		DBGPRINT(RT_DEBUG_TRACE,
+			 ("SendSignalToDaemon : Pid=%d\n",
+			  GET_PID_NUMBER(pid)));
+		KILL_THREAD_PID(pid, sig, 0);
+	}
+#if 0
+	if (pid != 0) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#define GET_PID(_pid)	find_get_pid(_pid)
+#else
+#define GET_PID(_pid)	(_pid)
+#endif
+
+		KILL_THREAD_PID(pid), sig, 0);
+	}
+#endif
+#endif
+}
+#endif /* CONFIG_AP_SUPPORT */
+
+#ifdef CONFIG_STA_SUPPORT
+INT32 ralinkrate[] = {
+2, 4, 11, 22,		/* CCK */
+12, 18, 24, 36, 48, 72, 96, 108,	/* OFDM */
+/* 20MHz, 800ns GI, MCS: 0 ~ 15 */
+13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78, 104, 156, 208, 234, 260,
+39, 78, 117, 156, 234, 312, 351, 390,	/* 20MHz, 800ns GI, MCS: 16 ~ 23 */
+/* 40MHz, 800ns GI, MCS: 0 ~ 15 */
+27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540,
+81, 162, 243, 324, 486, 648, 729, 810,	/* 40MHz, 800ns GI, MCS: 16 ~ 23 */
+/* 20MHz, 400ns GI, MCS: 0 ~ 15 */
+14, 29, 43, 57, 87, 115, 130, 144, 29, 59, 87, 115, 173, 230, 260, 288,
+43, 87, 130, 173, 260, 317, 390, 433,	/* 20MHz, 400ns GI, MCS: 16 ~ 23 */
+/* 40MHz, 400ns GI, MCS: 0 ~ 15 */
+30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600,
+90, 180, 270, 360, 540, 720, 810, 900};	/* 40MHz, 400ns GI, MCS: 16 ~ 23 */
+
+UINT32 RT_RateSize = sizeof (ralinkrate);
+
+void send_monitor_packets(IN PNET_DEV pNetDev,
+			  IN PNDIS_PACKET pRxPacket,
+			  IN PHEADER_802_11 pHeader,
+			  IN UCHAR * pData,
+			  IN USHORT DataSize,
+			  IN UCHAR L2PAD,
+			  IN UCHAR PHYMODE,
+			  IN UCHAR BW,
+			  IN UCHAR ShortGI,
+			  IN UCHAR MCS,
+			  IN UCHAR AMPDU,
+			  IN UCHAR STBC,
+			  IN UCHAR RSSI1,
+			  IN UCHAR BssMonitorFlag11n,
+			  IN UCHAR * pDevName,
+			  IN UCHAR Channel,
+			  IN UCHAR CentralChannel,
+			  IN UINT32 MaxRssi) {
+	struct sk_buff *pOSPkt;
+	wlan_ng_prism2_header *ph;
+#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT
+	ETHEREAL_RADIO h,
+	*ph_11n33;		/* for new 11n sniffer format */
+#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */
+	int rate_index = 0;
+	USHORT header_len = 0;
+	UCHAR temp_header[40] = {
+	0};
+
+	MEM_DBG_PKT_FREE_INC(pRxPacket);
+
+#if 0 /* os abl move */
+	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;
+	}
+#endif
+
+	pOSPkt = RTPKT_TO_OSPKT(pRxPacket);	/*pRxBlk->pRxPacket); */
+	pOSPkt->dev = pNetDev;	/*get_netdev_from_bssid(pAd, BSS0); */
+	if (pHeader->FC.Type == BTYPE_DATA) {
+		DataSize -= LENGTH_802_11;
+		if ((pHeader->FC.ToDs == 1) && (pHeader->FC.FrDs == 1))
+			header_len = LENGTH_802_11_WITH_ADDR4;
+		else
+			header_len = LENGTH_802_11;
+
+		/* QOS */
+		if (pHeader->FC.SubType & 0x08) {
+			header_len += 2;
+			/* Data skip QOS contorl field */
+			DataSize -= 2;
+		}
+
+		/* Order bit: A-Ralink or HTC+ */
+		if (pHeader->FC.Order) {
+			header_len += 4;
+			/* Data skip HTC contorl field */
+			DataSize -= 4;
+		}
+
+		/* Copy Header */
+		if (header_len <= 40)
+			NdisMoveMemory(temp_header, pData, header_len);
+
+		/* skip HW padding */
+		if (L2PAD)
+			pData += (header_len + 2);
+		else
+			pData += header_len;
+	}
+
+	if (DataSize < pOSPkt->len) {
+		skb_trim(pOSPkt, DataSize);
+	} else {
+		skb_put(pOSPkt, (DataSize - pOSPkt->len));
+	}
+
+	if ((pData - pOSPkt->data) > 0) {
+		skb_put(pOSPkt, (pData - pOSPkt->data));
+		skb_pull(pOSPkt, (pData - pOSPkt->data));
+	}
+
+	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;
+		}
+	}
+
+	if (header_len > 0)
+		NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header,
+			       header_len);
+
+#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT
+	if (BssMonitorFlag11n == 0)
+#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */
+	{
+		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) pDevName);
+
+		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) Channel;
+
+		ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
+		ph->rssi.status = 0;
+		ph->rssi.len = 4;
+		ph->rssi.data = MaxRssi;
+#if 0
+		(u_int32_t) RTMPMaxRssiOrg(pAd
+			, ConvertToRssiOrg(pAd, pRxBlk->pRxWI->RxWIRSSI0, RSSI_0)
+			, ConvertToRssiOrg(pAd, pRxBlk->pRxWI->RxWIRSSI1, RSSI_1)
+			, ConvertToRssiOrg(pAd, pRxBlk->pRxWI->RxWIRSSI2, RSSI_2));
+#endif
+		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 (PHYMODE >= MODE_HTMIX) {
+			rate_index = 12 + ((UCHAR) BW * 24) + ((UCHAR) ShortGI * 48) + ((UCHAR) MCS);
+		} else
+#endif /* DOT11_N_SUPPORT */
+		if (PHYMODE == MODE_OFDM)
+			rate_index = (UCHAR) (MCS) + 4;
+		else
+			rate_index = (UCHAR) (MCS);
+
+		if (rate_index < 0)
+			rate_index = 0;
+		if (rate_index >= (sizeof (ralinkrate) / sizeof (ralinkrate[0])))
+			rate_index = (sizeof (ralinkrate) / sizeof (ralinkrate[0])) - 1;
+
+		ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
+		ph->rate.status = 0;
+		ph->rate.len = 4;
+		/* real rate = ralinkrate[rate_index] / 2 */
+		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) DataSize;
+	}
+#ifdef MONITOR_FLAG_11N_SNIFFER_SUPPORT
+	else {
+		ph_11n33 = &h;
+		NdisZeroMemory((unsigned char *)ph_11n33,
+			       sizeof (ETHEREAL_RADIO));
+
+		/*802.11n fields */
+		if (MCS > 15)
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_3x3;
+
+		if (PHYMODE == MODE_HTGREENFIELD)
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_GF;
+
+		if (BW == 1) {
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW40;
+		} else if (Channel < CentralChannel) {
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW20U;
+		} else if (Channel > CentralChannel) {
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_BW20D;
+		} else {
+			ph_11n33->Flag_80211n |=
+			    (WIRESHARK_11N_FLAG_BW20U |
+			     WIRESHARK_11N_FLAG_BW20D);
+		}
+
+		if (ShortGI == 1)
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_SGI;
+
+		if (AMPDU)
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_AMPDU;
+
+		if (STBC)
+			ph_11n33->Flag_80211n |= WIRESHARK_11N_FLAG_STBC;
+
+		ph_11n33->signal_level = (UCHAR) RSSI1;
+
+		/* data_rate is the rate index in the wireshark rate table */
+		if (PHYMODE >= MODE_HTMIX) {
+			if (MCS == 32) {
+				if (ShortGI)
+					ph_11n33->data_rate = 16;
+				else
+					ph_11n33->data_rate = 4;
+			} else if (MCS > 15)
+				ph_11n33->data_rate =
+				    (16 * 4 + ((UCHAR) BW * 16) +
+				     ((UCHAR) ShortGI * 32) + ((UCHAR) MCS));
+			else
+				ph_11n33->data_rate =
+				    16 + ((UCHAR) BW * 16) +
+				    ((UCHAR) ShortGI * 32) + ((UCHAR) MCS);
+		} else if (PHYMODE == MODE_OFDM)
+			ph_11n33->data_rate = (UCHAR) (MCS) + 4;
+		else
+			ph_11n33->data_rate = (UCHAR) (MCS);
+
+		/*channel field */
+		ph_11n33->channel = (UCHAR) Channel;
+
+		NdisMoveMemory(skb_put(pOSPkt, sizeof (ETHEREAL_RADIO)),
+			       (UCHAR *) ph_11n33, sizeof (ETHEREAL_RADIO));
+	}
+#endif /* MONITOR_FLAG_11N_SNIFFER_SUPPORT */
+
+	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(NULL, 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;
+
+	if (flag == RTMP_FILE_RDONLY)
+		flag = O_RDONLY;
+	else if (flag == RTMP_FILE_WRONLY)
+		flag = O_WRONLY;
+	else if (flag == RTMP_FILE_CREAT)
+		flag = O_CREAT;
+	else if (flag == RTMP_FILE_TRUNC)
+		flag = O_TRUNC;
+
+	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);
+}
+
+static inline void __RtmpOSFSInfoChange(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.
+
+ *******************************************************************************/
+static inline NDIS_STATUS __RtmpOSTaskKill(OS_TASK *pTask)
+{
+	int ret = NDIS_STATUS_FAILURE;
+
+#ifdef KTHREAD_SUPPORT
+	if (pTask->kthread_task) {
+		kthread_stop(pTask->kthread_task);
+		ret = NDIS_STATUS_SUCCESS;
+	}
+#else
+	CHECK_PID_LEGALITY(pTask->taskPID) {
+		DBGPRINT(RT_DEBUG_TRACE,
+			 ("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;
+			RTMP_SEM_EVENT_DESTORY(&pTask->taskSema);
+			ret = NDIS_STATUS_SUCCESS;
+		}
+	}
+#endif
+
+	return ret;
+
+}
+
+static inline INT __RtmpOSTaskNotifyToExit(OS_TASK *pTask)
+{
+#ifndef KTHREAD_SUPPORT
+	pTask->taskPID = THREAD_PID_INIT_VALUE;
+	complete_and_exit(&pTask->taskComplete, 0);
+#endif
+
+	return 0;
+}
+
+static inline void __RtmpOSTaskCustomize(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(&current->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(&current->sigmask_lock, flags);
+	flush_signals(current);
+	recalc_sigpending(current);
+	spin_unlock_irqrestore(&current->sigmask_lock, flags);
+#endif
+#endif
+
+	RTMP_GET_OS_PID(pTask->taskPID, current->pid);
+
+	/* signal that we've started the thread */
+	complete(&pTask->taskComplete);
+
+#endif
+}
+
+static inline NDIS_STATUS __RtmpOSTaskAttach(
+	IN OS_TASK *pTask,
+	IN RTMP_OS_TASK_CALLBACK fn,
+	IN ULONG arg)
+{
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+#ifndef KTHREAD_SUPPORT
+	pid_t pid_number = -1;
+#endif /* KTHREAD_SUPPORT */
+
+#ifdef KTHREAD_SUPPORT
+	pTask->task_killed = 0;
+	pTask->kthread_task = NULL;
+	pTask->kthread_task =
+	    kthread_run((cast_fn) fn, (void *)arg, pTask->taskName);
+	if (IS_ERR(pTask->kthread_task))
+		status = NDIS_STATUS_FAILURE;
+#else
+	pid_number =
+	    kernel_thread((cast_fn) fn, (void *)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 {
+		/* Wait for the thread to start */
+		wait_for_completion(&pTask->taskComplete);
+		status = NDIS_STATUS_SUCCESS;
+	}
+#endif
+	return status;
+}
+
+static inline NDIS_STATUS __RtmpOSTaskInit(
+	IN OS_TASK *pTask,
+	IN PSTRING pTaskName,
+	IN VOID *pPriv,
+	IN LIST_HEADER *pSemList)
+{
+	int len;
+
+	ASSERT(pTask);
+
+#ifndef KTHREAD_SUPPORT
+	NdisZeroMemory((PUCHAR) (pTask), sizeof (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), pSemList);
+	pTask->taskPID = THREAD_PID_INIT_VALUE;
+	init_completion(&pTask->taskComplete);
+#endif
+
+#ifdef KTHREAD_SUPPORT
+	init_waitqueue_head(&(pTask->kthread_q));
+#endif /* KTHREAD_SUPPORT */
+
+	return NDIS_STATUS_SUCCESS;
+}
+
+BOOLEAN __RtmpOSTaskWait(
+	IN VOID *pReserved,
+	IN OS_TASK *pTask,
+	IN INT32 *pStatus)
+{
+#ifdef KTHREAD_SUPPORT
+	RTMP_WAIT_EVENT_INTERRUPTIBLE((*pStatus), pTask);
+
+	if ((pTask->task_killed == 1) || ((*pStatus) != 0))
+		return FALSE;
+#else
+
+	RTMP_SEM_EVENT_WAIT(&(pTask->taskSema), (*pStatus));
+
+	/* unlock the device pointers */
+	if ((*pStatus) != 0) {
+/*		RTMP_SET_FLAG_(*pFlags, fRTMP_ADAPTER_HALT_IN_PROGRESS); */
+		return FALSE;
+	}
+#endif /* KTHREAD_SUPPORT */
+
+	return TRUE;
+}
+
+#if 0 /* os abl move to os/linux/rt_profile.c */
+void RTMP_IndicateMediaState(IN PRTMP_ADAPTER pAd,
+			     IN NDIS_MEDIA_STATE media_state) {
+	pAd->IndicateMediaState = media_state;
+#ifdef SYSTEM_LOG_SUPPORT
+	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);
+	}
+#endif /* SYSTEM_LOG_SUPPORT */
+}
+#endif
+
+#if LINUX_VERSION_CODE <= 0x20402	/* Red Hat 7.1 */
+#if 0
+static struct net_device *alloc_netdev(int sizeof_priv, const char *mask
+		, void (*setup)(struct net_device *)) //sample
+#endif
+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 */
+
+
+static UINT32 RtmpOSWirelessEventTranslate(IN UINT32 eventType)
+{
+	switch (eventType) {
+	case RT_WLAN_EVENT_CUSTOM:
+		eventType = IWEVCUSTOM;
+		break;
+
+	case RT_WLAN_EVENT_CGIWAP:
+		eventType = SIOCGIWAP;
+		break;
+
+#if WIRELESS_EXT > 17
+	case RT_WLAN_EVENT_ASSOC_REQ_IE:
+		eventType = IWEVASSOCREQIE;
+		break;
+#endif /* WIRELESS_EXT */
+
+#if WIRELESS_EXT >= 14
+	case RT_WLAN_EVENT_SCAN:
+		eventType = SIOCGIWSCAN;
+		break;
+#endif /* WIRELESS_EXT */
+
+	case RT_WLAN_EVENT_EXPIRED:
+		eventType = IWEVEXPIRED;
+		break;
+#ifdef P2P_SUPPORT
+	case RT_WLAN_EVENT_SHOWPIN:
+		eventType = 0x8C05; /* IWEVP2PKEYSHOWPIN; */
+		break;
+	case RT_WLAN_EVENT_PIN:
+		eventType = 0x8C06; /* IWEVP2PKEYPIN; */
+		break;
+#endif /* P2P_SUPPORT */
+
+	default:
+		printk("Unknown event: 0x%x\n", eventType);
+		break;
+	}
+
+	return eventType;
+}
+
+int RtmpOSWrielessEventSend(
+	IN PNET_DEV pNetDev,
+	IN UINT32 eventType,
+	IN INT flags,
+	IN PUCHAR pSrcMac,
+	IN PUCHAR pData,
+	IN UINT32 dataLen)
+{
+#ifdef DPA_S
+	RtmpOSNotifyRawData(pNetDev, &flags, sizeof(flags), 0, ETH_P_DPA_S_NOTIF);
+#else
+	union iwreq_data wrqu;
+
+	/* translate event type */
+	eventType = RtmpOSWirelessEventTranslate(eventType);
+
+	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;
+	else
+		wrqu.data.length = 0;
+
+	wireless_send_event(pNetDev, eventType, &wrqu, (char *)pData);
+#endif
+	return 0;
+}
+
+int RtmpOSWrielessEventSendExt(
+	IN PNET_DEV pNetDev,
+	IN UINT32 eventType,
+	IN INT flags,
+	IN PUCHAR pSrcMac,
+	IN PUCHAR pData,
+	IN UINT32 dataLen,
+	IN UINT32 family)
+{
+	union iwreq_data wrqu;
+
+	/* translate event type */
+	eventType = RtmpOSWirelessEventTranslate(eventType);
+
+	/* translate event type */
+	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;
+
+	wrqu.addr.sa_family = family;
+
+	wireless_send_event(pNetDev, eventType, &wrqu, (char *)pData);
+	return 0;
+}
+
+int RtmpOSNetDevAddrSet(
+	IN UCHAR OpMode,
+	IN PNET_DEV pNetDev,
+	IN PUCHAR pMacAddr,
+	IN PUCHAR dev_name)
+{
+	struct net_device *net_dev;
+
+	net_dev = pNetDev;
+/*	GET_PAD_FROM_NET_DEV(pAd, net_dev); */
+
+#ifdef CONFIG_STA_SUPPORT
+	/* work-around for the SuSE due to it has it's own interface name management system. */
+	RT_CONFIG_IF_OPMODE_ON_STA(OpMode) {
+/*		NdisZeroMemory(pAd->StaCfg.dev_name, 16); */
+/*		NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name)); */
+		if (dev_name != NULL) {
+			NdisZeroMemory(dev_name, 16);
+			NdisMoveMemory(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 INT32 MC_RowID,
+	IN UINT32 *pIoctlIF,
+	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 (MC_RowID >= 0)
+			sprintf(suffixName, "%02d_%d", 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) {
+#ifdef HOSTAPD_SUPPORT
+		*pIoctlIF = ifNameIdx;
+#endif /*HOSTAPD_SUPPORT */
+		strcpy(&dev->name[0], &desiredName[0]);
+#ifdef RELEASE_EXCLUDE
+		DBGPRINT(RT_DEBUG_INFO,
+			 ("Assign the net device name as %s\n", &dev->name[0]));
+#endif /* RELEASE_EXCLUDE */
+		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(PNET_DEV pNetDev)
+{
+	dev_close(pNetDev);
+}
+
+void RtmpOSNetDevFree(PNET_DEV pNetDev)
+{
+	DEV_PRIV_INFO *pDevInfo = NULL;
+
+
+	ASSERT(pNetDev);
+
+	/* free assocaited private information */
+	pDevInfo = _RTMP_OS_NETDEV_GET_PRIV(pNetDev);
+	if (pDevInfo != NULL)
+		os_free_mem(NULL, pDevInfo);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+	free_netdev(pNetDev);
+#else
+	kfree(pNetDev);
+#endif
+
+#ifdef VENDOR_FEATURE4_SUPPORT
+	printk("OS_NumOfMemAlloc = %ld, OS_NumOfMemFree = %ld\n",
+			OS_NumOfMemAlloc, OS_NumOfMemFree);
+#endif /* VENDOR_FEATURE4_SUPPORT */
+#ifdef VENDOR_FEATURE2_SUPPORT
+	printk("OS_NumOfPktAlloc = %ld, OS_NumOfPktFree = %ld\n",
+			OS_NumOfPktAlloc, OS_NumOfPktFree);
+#endif /* VENDOR_FEATURE2_SUPPORT */
+}
+
+INT RtmpOSNetDevAlloc(
+	IN PNET_DEV *new_dev_p,
+	IN UINT32 privDataSize)
+{
+	*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;
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+INT RtmpOSNetDevOpsAlloc(PVOID *pNetDevOps)
+{
+	*pNetDevOps = (PVOID) vmalloc(sizeof (struct net_device_ops));
+	if (*pNetDevOps) {
+		NdisZeroMemory(*pNetDevOps, sizeof (struct net_device_ops));
+		return NDIS_STATUS_SUCCESS;
+	} else {
+		return NDIS_STATUS_FAILURE;
+	}
+}
+#endif
+
+
+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(VOID *pReserved, 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)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+	struct net_device_ops *pNetDevOps = (struct net_device_ops *)pNetDev->netdev_ops;
+#endif
+	int ret;
+
+	 ret = rtnl_trylock();
+
+	unregister_netdevice(pNetDev);
+
+	if ( ret )
+		rtnl_unlock();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+	vfree(pNetDevOps);
+#endif
+}
+
+
+void RtmpOSNetDevProtect(BOOLEAN lock_it)
+{
+
+/*
+	if (lock_it)
+		rtnl_lock();
+	else
+		rtnl_unlock();
+*/
+}
+
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
+static void RALINK_ET_DrvInfoGet(
+	struct net_device *pDev,
+	struct ethtool_drvinfo *pInfo)
+{
+	strcpy(pInfo->driver, "RALINK WLAN");
+
+#if 0 /* os abl move */
+#ifdef CONFIG_AP_SUPPORT
+	strcpy(pInfo->version, AP_DRIVER_VERSION);
+#endif				/* CONFIG_AP_SUPPORT */
+#ifdef CONFIG_STA_SUPPORT
+	strcpy(pInfo->version, STA_DRIVER_VERSION);
+#endif				/* CONFIG_STA_SUPPORT */
+#endif
+
+	sprintf(pInfo->bus_info, "CSR 0x%lx", pDev->base_addr);
+}
+
+static struct ethtool_ops RALINK_Ethtool_Ops = {
+	.get_drvinfo = RALINK_ET_DrvInfoGet,
+};
+#endif
+
+
+int RtmpOSNetDevAttach(
+	IN UCHAR OpMode,
+	IN PNET_DEV pNetDev,
+	IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook)
+{
+	int ret,
+	 rtnl_locked = FALSE;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+	struct net_device_ops *pNetDevOps = (struct net_device_ops *)pNetDev->netdev_ops;
+#endif
+
+	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 = NULL; */
+
+/*		GET_PAD_FROM_NET_DEV(pAd, pNetDev); */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+		pNetDevOps->ndo_open = pDevOpHook->open;
+		pNetDevOps->ndo_stop = pDevOpHook->stop;
+		pNetDevOps->ndo_start_xmit =
+		    (HARD_START_XMIT_FUNC) (pDevOpHook->xmit);
+		pNetDevOps->ndo_do_ioctl = pDevOpHook->ioctl;
+#else
+		pNetDev->open = pDevOpHook->open;
+		pNetDev->stop = pDevOpHook->stop;
+		pNetDev->hard_start_xmit =
+		    (HARD_START_XMIT_FUNC) (pDevOpHook->xmit);
+		pNetDev->do_ioctl = pDevOpHook->ioctl;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
+		pNetDev->ethtool_ops = &RALINK_Ethtool_Ops;
+#endif
+
+		/* if you don't implement get_stats, just leave the callback function as NULL, a dummy 
+		   function will make kernel panic.
+		 */
+		if (pDevOpHook->get_stats)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+			pNetDevOps->ndo_get_stats = pDevOpHook->get_stats;
+#else
+			pNetDev->get_stats = pDevOpHook->get_stats;
+#endif
+
+		/* OS specific flags, here we used to indicate if we are virtual interface */
+/*		pNetDev->priv_flags = pDevOpHook->priv_flags; */
+		RT_DEV_PRIV_FLAGS_SET(pNetDev, pDevOpHook->priv_flags);
+
+#if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12)
+/*		pNetDev->get_wireless_stats = rt28xx_get_wireless_stats; */
+		pNetDev->get_wireless_stats = pDevOpHook->get_wstats;
+#endif
+
+#ifdef CONFIG_STA_SUPPORT
+#if WIRELESS_EXT >= 12
+		if (OpMode == OPMODE_STA) {
+/*			pNetDev->wireless_handlers = &rt28xx_iw_handler_def; */
+			pNetDev->wireless_handlers = pDevOpHook->iw_handler;
+		}
+#endif /*WIRELESS_EXT >= 12 */
+#endif /* CONFIG_STA_SUPPORT */
+
+#ifdef CONFIG_APSTA_MIXED_SUPPORT
+#if WIRELESS_EXT >= 12
+		if (OpMode == OPMODE_AP) {
+/*			pNetDev->wireless_handlers = &rt28xx_ap_iw_handler_def; */
+			pNetDev->wireless_handlers = pDevOpHook->iw_handler;
+		}
+#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 0 /* os abl move */
+#ifdef RT_CFG80211_SUPPORT
+		/*
+		   In 2.6.32, cfg80211 register must be before register_netdevice();
+		   We can not put the register in rt28xx_open();
+		   Or you will suffer NULL pointer in list_add of
+		   cfg80211_netdev_notifier_call().
+		 */
+		RT_CFG80211_REGISTER(pAd, pAd->pCfgDev, pNetDev);
+#endif /* RT_CFG80211_SUPPORT */
+#endif
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+	pNetDevOps->ndo_validate_addr = NULL;
+	/*pNetDev->netdev_ops = ops; */
+#else
+	pNetDev->validate_addr = NULL;
+#endif
+#endif
+
+	if (rtnl_locked)
+		ret = register_netdevice(pNetDev);
+	else
+		ret = register_netdev(pNetDev);
+
+	netif_stop_queue(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 INT32 MC_RowID,
+	IN UINT32 *pIoctlIF,
+	IN INT devType,
+	IN INT devNum,
+	IN INT privMemSize,
+	IN PSTRING pNamePrefix)
+{
+	struct net_device *pNetDev = NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+	struct net_device_ops *pNetDevOps = NULL;
+#endif
+	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;
+	}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
+	status = RtmpOSNetDevOpsAlloc((PVOID) & pNetDevOps);
+	if (status != NDIS_STATUS_SUCCESS) {
+		/* error! no any available ra name can be used! */
+		DBGPRINT(RT_DEBUG_TRACE, ("Allocate net device ops fail!\n"));
+		RtmpOSNetDevFree(pNetDev);
+
+		return NULL;
+	} else {
+		DBGPRINT(RT_DEBUG_TRACE, ("Allocate net device ops success!\n"));
+		pNetDev->netdev_ops = pNetDevOps;
+	}
+#endif
+	/* find a available interface name, max 32 interfaces */
+	status = RtmpOSNetDevRequestName(MC_RowID, pIoctlIF, 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;
+}
+
+#if 0 /* os abl move to common/rtmp_init.c */
+/* OS_ABL_SUPPORT */
+/* not yet support MBSS */
+PNET_DEV get_netdev_from_bssid(IN PRTMP_ADAPTER pAd,
+			       IN UCHAR FromWhichBSSID) {
+	PNET_DEV dev_p = NULL;
+
+#ifdef MESH_SUPPORT
+	if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_MESH) {
+		dev_p = pAd->MeshTab.dev;
+	} else
+#endif /* MESH_SUPPORT */
+#ifdef CONFIG_AP_SUPPORT
+		IF_DEV_CONFIG_OPMODE_ON_AP(pAd) {
+		UCHAR infRealIdx;
+
+		infRealIdx = FromWhichBSSID & (NET_DEVICE_REAL_IDX_MASK);
+#ifdef APCLI_SUPPORT
+		if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_APCLI) {
+			dev_p =
+			    (infRealIdx >=
+			     MAX_APCLI_NUM ? NULL : pAd->ApCfg.
+			     ApCliTab[infRealIdx].dev);
+		} else
+#endif /* APCLI_SUPPORT */
+#ifdef WDS_SUPPORT
+		if (FromWhichBSSID >= MIN_NET_DEVICE_FOR_WDS) {
+			dev_p =
+			    ((infRealIdx >=
+			      MAX_WDS_ENTRY) ? NULL : pAd->WdsTab.
+			     WdsEntry[infRealIdx].dev);
+		} else
+#endif /* WDS_SUPPORT */
+		{
+			if (FromWhichBSSID >= pAd->ApCfg.BssidNum) {
+				DBGPRINT(RT_DEBUG_ERROR,
+					 ("%s: fatal error ssid > ssid num!\n",
+					  __FUNCTION__));
+				dev_p = pAd->net_dev;
+			}
+
+			if (FromWhichBSSID == BSS0)
+				dev_p = pAd->net_dev;
+			else {
+				dev_p =
+				    pAd->ApCfg.MBSSID[FromWhichBSSID].MSSIDDev;
+			}
+		}
+		}
+#endif /* CONFIG_AP_SUPPORT */
+
+#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 */
+}
+#endif
+
+
+#ifdef CONFIG_AP_SUPPORT
+UCHAR VLAN_8023_Header_Copy(
+	IN USHORT VLAN_VID,
+	IN USHORT VLAN_Priority,
+	IN PUCHAR pHeader802_3,
+	IN UINT HdrLen,
+	OUT PUCHAR pData,
+	IN UCHAR FromWhichBSSID,
+	IN UCHAR *TPID)
+{
+	UINT16 TCI;
+	UCHAR VLAN_Size = 0;
+
+	if (VLAN_VID != 0) {
+		/* need to insert VLAN tag */
+		VLAN_Size = LENGTH_802_1Q;
+
+		/* make up TCI field */
+		TCI = (VLAN_VID & 0x0fff) | ((VLAN_Priority & 0x7) << 13);
+
+#ifndef RT_BIG_ENDIAN
+		TCI = SWAP16(TCI);
+#endif /* RT_BIG_ENDIAN */
+
+		/* copy dst + src MAC (12B) */
+		memcpy(pData, pHeader802_3, LENGTH_802_3_NO_TYPE);
+
+		/* copy VLAN tag (4B) */
+		/* do NOT use memcpy to speed up */
+		*(UINT16 *) (pData + LENGTH_802_3_NO_TYPE) = *(UINT16 *) TPID;
+		*(UINT16 *) (pData + LENGTH_802_3_NO_TYPE + 2) = TCI;
+
+		/* copy type/len (2B) */
+		*(UINT16 *) (pData + LENGTH_802_3_NO_TYPE + LENGTH_802_1Q) =
+		    *(UINT16 *) & pHeader802_3[LENGTH_802_3 -
+					       LENGTH_802_3_TYPE];
+
+		/* copy tail if exist */
+		if (HdrLen > LENGTH_802_3)
+			memcpy(pData + LENGTH_802_3 + LENGTH_802_1Q, pHeader802_3 + LENGTH_802_3, HdrLen - LENGTH_802_3);
+	}
+	else
+	{
+		/* no VLAN tag is needed to insert */
+		memcpy(pData, pHeader802_3, HdrLen);
+	}
+	
+	return VLAN_Size;
+}				
+#endif /* CONFIG_AP_SUPPORT */
+
+
+/*
+========================================================================
+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(VOID *handle, VOID **ppAd, UINT32 SizeOfpAd)
+{
+#ifdef OS_ABL_FUNC_SUPPORT
+	/* get offset for sk_buff */
+	{
+		struct sk_buff *pPkt = NULL;
+
+		pPkt = kmalloc(sizeof (struct sk_buff), GFP_ATOMIC);
+		if (pPkt == NULL) {
+			*ppAd = NULL;
+			return NDIS_STATUS_FAILURE;
+		}
+
+		RTPktOffsetData = (ULONG) (&(pPkt->data)) - (ULONG) pPkt;
+		RTPktOffsetLen = (ULONG) (&(pPkt->len)) - (ULONG) pPkt;
+		RTPktOffsetCB = (ULONG) (pPkt->cb) - (ULONG) pPkt;
+		kfree(pPkt);
+
+		DBGPRINT(RT_DEBUG_TRACE, ("packet> data offset = %lu\n", RTPktOffsetData));
+		DBGPRINT(RT_DEBUG_TRACE, ("packet> len offset = %lu\n", RTPktOffsetLen));
+		DBGPRINT(RT_DEBUG_TRACE, ("packet> cb offset = %lu\n", RTPktOffsetCB));
+	}
+#endif /* OS_ABL_FUNC_SUPPORT */
+
+/*	*ppAd = (PVOID)vmalloc(sizeof(RTMP_ADAPTER)); //pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); */
+	*ppAd = (PVOID) vmalloc(SizeOfpAd);	/*pci_alloc_consistent(pci_dev, sizeof(RTMP_ADAPTER), phy_addr); */
+	if (*ppAd) {
+		NdisZeroMemory(*ppAd, SizeOfpAd);
+		return NDIS_STATUS_SUCCESS;
+	} else
+		return NDIS_STATUS_FAILURE;
+}
+
+
+/* ========================================================================== */
+
+UINT RtmpOsWirelessExtVerGet(VOID)
+{
+	return WIRELESS_EXT;
+}
+
+
+VOID RtmpDrvAllMacPrint(
+	IN VOID *pReserved,
+	IN UINT32 *pBufMac,
+	IN UINT32 AddrStart,
+	IN UINT32 AddrEnd,
+	IN UINT32 AddrStep)
+{
+	struct file *file_w;
+	PSTRING fileName = "MacDump.txt";
+	mm_segment_t orig_fs;
+	STRING *msg;
+	UINT32 macAddr = 0, macValue = 0;
+
+	os_alloc_mem(NULL, (UCHAR **)&msg, 1024);
+	if (!msg)
+		return;
+	
+	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 = AddrStart;
+
+			while (macAddr <= AddrEnd) {
+/*				RTMP_IO_READ32(pAd, macAddr, &macValue); // sample */
+				macValue = *pBufMac++;
+				sprintf(msg, "%04x = %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 += AddrStep;
+			}
+			sprintf(msg, "\nDump all MAC values to %s\n", fileName);
+		}
+		filp_close(file_w, NULL);
+	}
+	set_fs(orig_fs);
+	os_free_mem(NULL, msg);
+}
+
+
+VOID RtmpDrvAllE2PPrint(
+	IN VOID *pReserved,
+	IN USHORT *pMacContent,
+	IN UINT32 AddrEnd,
+	IN UINT32 AddrStep)
+{
+	struct file *file_w;
+	PSTRING fileName = "EEPROMDump.txt";
+	mm_segment_t orig_fs;
+	STRING *msg;
+	USHORT eepAddr = 0;
+	USHORT eepValue;
+
+	os_alloc_mem(NULL, (UCHAR **)&msg, 1024);
+	if (!msg)
+		return;
+	
+	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 <= AddrEnd) {
+				eepValue = *pMacContent;
+				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 += AddrStep;
+				pMacContent += (AddrStep >> 1);
+			}
+			sprintf(msg, "\nDump all EEPROM values to %s\n",
+				fileName);
+		}
+		filp_close(file_w, NULL);
+	}
+	set_fs(orig_fs);
+	os_free_mem(NULL, msg);
+}
+
+
+VOID RtmpDrvAllRFPrint(
+	IN VOID *pReserved,
+	IN UINT32 *pBuf,
+	IN UINT32 BufLen)
+{
+	struct file *file_w;
+	PSTRING fileName = "RFDump.txt";
+	mm_segment_t orig_fs;
+	UINT32 macAddr = 0, macValue = 0;
+	
+	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;
+			/* write data to file */
+			file_w->f_op->write(file_w, pBuf, BufLen, &file_w->f_pos);
+		}
+		filp_close(file_w, NULL);
+	}
+	set_fs(orig_fs);
+}
+
+/*
+========================================================================
+Routine Description:
+	Check if the network interface is up.
+
+Arguments:
+	*pDev			- Network Interface
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOSNetDevIsUp(VOID *pDev)
+{
+	struct net_device *pNetDev = (struct net_device *)pDev;
+
+	if ((pNetDev == NULL) || !(pNetDev->flags & IFF_UP))
+		return FALSE;
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Wake up the command thread.
+
+Arguments:
+	pAd				- WLAN control block pointer
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsCmdUp(RTMP_OS_TASK *pCmdQTask)
+{
+	OS_TASK *pTask = RTMP_OS_TASK_GET(pCmdQTask);
+#ifdef KTHREAD_SUPPORT
+	pTask->kthread_running = TRUE;
+	wake_up(&pTask->kthread_q);
+#else
+	CHECK_PID_LEGALITY(pTask->taskPID) {
+		RTMP_SEM_EVENT_UP(&(pTask->taskSema));
+	}
+#endif /* KTHREAD_SUPPORT */
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Wake up USB Mlme thread.
+
+Arguments:
+	pAd				- WLAN control block pointer
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsMlmeUp(IN RTMP_OS_TASK *pMlmeQTask)
+{
+#ifdef RTMP_USB_SUPPORT
+	OS_TASK *pTask = RTMP_OS_TASK_GET(pMlmeQTask);
+
+#ifdef KTHREAD_SUPPORT
+	if ((pTask != NULL) && (pTask->kthread_task)) {
+		pTask->kthread_running = TRUE;
+		wake_up(&pTask->kthread_q);
+	}
+#else
+	if (pTask != NULL) {
+		CHECK_PID_LEGALITY(pTask->taskPID) {
+			RTMP_SEM_EVENT_UP(&(pTask->taskSema));
+		}
+	}
+#endif /* KTHREAD_SUPPORT */
+#endif /* RTMP_USB_SUPPORT */
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Check if the file is error.
+
+Arguments:
+	pFile			- the file
+
+Return Value:
+	OK or any error
+
+Note:
+	rt_linux.h, not rt_drv.h
+========================================================================
+*/
+INT32 RtmpOsFileIsErr(IN VOID *pFile)
+{
+	return IS_FILE_OPEN_ERR(pFile);
+}
+
+int RtmpOSIRQRelease(
+	IN PNET_DEV pNetDev,
+	IN UINT32 infType,
+	IN PPCI_DEV pci_dev,
+	IN BOOLEAN *pHaveMsi)
+{
+	struct net_device *net_dev = (struct net_device *)pNetDev;
+
+#ifdef RTMP_PCI_SUPPORT
+	if (infType == RTMP_DEV_INF_PCI || infType == RTMP_DEV_INF_PCIE) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+		synchronize_irq(pci_dev->irq);
+#endif
+		free_irq(pci_dev->irq, (net_dev));
+		RTMP_MSI_DISABLE(pci_dev, pHaveMsi);
+	}
+#endif /* RTMP_PCI_SUPPORT */
+
+#ifdef RTMP_RBUS_SUPPORT
+	if (infType == RTMP_DEV_INF_RBUS) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+		synchronize_irq(net_dev->irq);
+#endif
+		free_irq(net_dev->irq, (net_dev));
+	}
+#endif /* RTMP_RBUS_SUPPORT */
+
+	return 0;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Enable or disable wireless event sent.
+
+Arguments:
+	pReserved		- Reserved
+	FlgIsWEntSup	- TRUE or FALSE
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsWlanEventSet(
+	IN VOID *pReserved,
+	IN BOOLEAN *pCfgWEnt,
+	IN BOOLEAN FlgIsWEntSup)
+{
+#if WIRELESS_EXT >= 15
+/*	pAd->CommonCfg.bWirelessEvent = FlgIsWEntSup; */
+	*pCfgWEnt = FlgIsWEntSup;
+#else
+	*pCfgWEnt = 0;		/* disable */
+#endif
+}
+
+/*
+========================================================================
+Routine Description:
+	vmalloc
+
+Arguments:
+	Size			- memory size
+
+Return Value:
+	the memory
+
+Note:
+========================================================================
+*/
+VOID *RtmpOsVmalloc(ULONG Size)
+{
+	return vmalloc(Size);
+}
+
+/*
+========================================================================
+Routine Description:
+	vfree
+
+Arguments:
+	pMem			- the memory
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsVfree(VOID *pMem)
+{
+	if (pMem != NULL)
+		vfree(pMem);
+}
+
+/*
+========================================================================
+Routine Description:
+	Get network interface name.
+
+Arguments:
+	pDev			- the device
+
+Return Value:
+	the name
+
+Note:
+========================================================================
+*/
+char *RtmpOsGetNetDevName(VOID *pDev)
+{
+	return ((PNET_DEV) pDev)->name;
+}
+
+/*
+========================================================================
+Routine Description:
+	Assign protocol to the packet.
+
+Arguments:
+	pPkt			- the packet
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktProtocolAssign(PNDIS_PACKET pNetPkt)
+{
+	struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt);
+	pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
+}
+
+
+BOOLEAN RtmpOsStatsAlloc(
+	IN VOID **ppStats,
+	IN VOID **ppIwStats)
+{
+	os_alloc_mem(NULL, (UCHAR **) ppStats, sizeof (struct net_device_stats));
+	if ((*ppStats) == NULL)
+		return FALSE;
+	NdisZeroMemory((UCHAR *) *ppStats, sizeof (struct net_device_stats));
+
+#if WIRELESS_EXT >= 12
+	os_alloc_mem(NULL, (UCHAR **) ppIwStats, sizeof (struct iw_statistics));
+	if ((*ppIwStats) == NULL) {
+		os_free_mem(NULL, *ppStats);
+		return FALSE;
+	}
+	NdisZeroMemory((UCHAR *)* ppIwStats, sizeof (struct iw_statistics));
+#endif
+
+	return TRUE;
+}
+
+/*
+========================================================================
+Routine Description:
+	Pass the received packet to OS.
+
+Arguments:
+	pPkt			- the packet
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktRcvHandle(PNDIS_PACKET pNetPkt)
+{
+	struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt);
+#ifdef CONFIG_CSO_SUPPORT
+	struct net_device *pNetDev =  GET_OS_PKT_NETDEV(pNetPkt);
+
+	if (pNetDev->features & NETIF_F_HW_CSUM)
+	{	
+		if (RTMP_GET_TCP_CHKSUM_FAIL(pNetPkt))
+			pRxPkt->ip_summed = CHECKSUM_NONE;
+		else
+			pRxPkt->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+#endif /* CONFIG_CSO_SUPPORT  */
+
+#ifdef CONFIG_RX_CSO_SUPPORT
+
+	if (RTMP_GET_TCP_CHKSUM_FAIL(pNetPkt))
+		pRxPkt->ip_summed = CHECKSUM_NONE;
+	else
+		pRxPkt->ip_summed = CHECKSUM_UNNECESSARY;
+
+#endif
+
+	netif_rx(pRxPkt);
+}
+
+
+VOID RtmpOsTaskPidInit(RTMP_OS_PID *pPid)
+{
+	*pPid = THREAD_PID_INIT_VALUE;
+}
+
+/*
+========================================================================
+Routine Description:
+	Get the network interface for the packet.
+
+Arguments:
+	pPkt			- the packet
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+PNET_DEV RtmpOsPktNetDevGet(VOID *pPkt)
+{
+	return GET_OS_PKT_NETDEV(pPkt);
+}
+
+
+#ifdef IAPP_SUPPORT
+/* Layer 2 Update frame to switch/bridge */
+/* For any Layer2 devices, e.g., bridges, switches and other APs, the frame
+   can update their forwarding tables with the correct port to reach the new
+   location of the STA */
+typedef struct GNU_PACKED _RT_IAPP_L2_UPDATE_FRAME {
+
+	UCHAR DA[ETH_ALEN];	/* broadcast MAC address */
+	UCHAR SA[ETH_ALEN];	/* the MAC address of the STA that has just associated
+				   or reassociated */
+	USHORT Len;		/* 8 octets */
+	UCHAR DSAP;		/* null */
+	UCHAR SSAP;		/* null */
+	UCHAR Control;		/* reference to IEEE Std 802.2 */
+	UCHAR XIDInfo[3];	/* reference to IEEE Std 802.2 */
+} RT_IAPP_L2_UPDATE_FRAME, *PRT_IAPP_L2_UPDATE_FRAME;
+
+
+PNDIS_PACKET RtmpOsPktIappMakeUp(
+	IN PNET_DEV pNetDev,
+	IN UINT8 *pMac)
+{
+	RT_IAPP_L2_UPDATE_FRAME frame_body;
+	INT size = sizeof (RT_IAPP_L2_UPDATE_FRAME);
+	PNDIS_PACKET pNetBuf;
+
+	if (pNetDev == NULL)
+		return NULL;
+
+	pNetBuf = RtmpOSNetPktAlloc(NULL, size);
+	if (!pNetBuf) {
+		DBGPRINT(RT_DEBUG_ERROR, ("Error! Can't allocate a skb.\n"));
+		return NULL;
+	}
+
+	/* init the update frame body */
+	NdisZeroMemory(&frame_body, size);
+
+	memset(frame_body.DA, 0xFF, ETH_ALEN);
+	memcpy(frame_body.SA, pMac, ETH_ALEN);
+
+	frame_body.Len = OS_HTONS(ETH_ALEN);
+	frame_body.DSAP = 0;
+	frame_body.SSAP = 0x01;
+	frame_body.Control = 0xAF;
+
+	frame_body.XIDInfo[0] = 0x81;
+	frame_body.XIDInfo[1] = 1;
+	frame_body.XIDInfo[2] = 1 << 1;
+
+	SET_OS_PKT_NETDEV(pNetBuf, pNetDev);
+	skb_reserve(pNetBuf, 2);
+	memcpy(skb_put(pNetBuf, size), &frame_body, size);
+	return pNetBuf;
+}
+#endif /* IAPP_SUPPORT */
+
+
+VOID RtmpOsPktNatMagicTag(PNDIS_PACKET pNetPkt)
+{
+#ifdef RTMP_RBUS_SUPPORT
+#if !defined(CONFIG_RA_NAT_NONE)
+#if defined (CONFIG_RA_HW_NAT)  || defined (CONFIG_RA_HW_NAT_MODULE)
+	struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt);
+	FOE_MAGIC_TAG(pRxPkt) = FOE_MAGIC_WLAN;
+#endif /* CONFIG_RA_HW_NAT || CONFIG_RA_HW_NAT_MODULE */
+#endif /* CONFIG_RA_NAT_NONE */
+#endif /* RTMP_RBUS_SUPPORT */
+}
+
+VOID RtmpOsPktNatNone(PNDIS_PACKET pNetPkt)
+{
+#ifdef RTMP_RBUS_SUPPORT
+#if defined(CONFIG_RA_NAT_NONE)
+#if defined (CONFIG_RA_HW_NAT)  || defined (CONFIG_RA_HW_NAT_MODULE)
+	FOE_AI(((struct sk_buff *)pNetPkt)) = UN_HIT;
+#endif /* CONFIG_RA_HW_NAT || CONFIG_RA_HW_NAT_MODULE */
+#endif /* CONFIG_RA_NAT_NONE */
+#endif /* RTMP_RBUS_SUPPORT */
+}
+
+
+#ifdef RT_CFG80211_SUPPORT
+/* all available channels */
+UCHAR Cfg80211_Chan[] = {
+	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+
+	/* 802.11 UNI / HyperLan 2 */
+	36, 38, 40, 44, 46, 48, 52, 54, 56, 60, 62, 64,
+
+	/* 802.11 HyperLan 2 */
+	100, 104, 108, 112, 116, 118, 120, 124, 126, 128, 132, 134, 136,
+
+	/* 802.11 UNII */
+	140, 149, 151, 153, 157, 159, 161, 165, 167, 169, 171, 173,
+
+	/* Japan */
+	184, 188, 192, 196, 208, 212, 216,
+};
+
+/*
+	Array of bitrates the hardware can operate with
+	in this band. Must be sorted to give a valid "supported
+	rates" IE, i.e. CCK rates first, then OFDM.
+
+	For HT, assign MCS in another structure, ieee80211_sta_ht_cap.
+*/
+const struct ieee80211_rate Cfg80211_SupRate[12] = {
+	{
+		.flags = IEEE80211_RATE_SHORT_PREAMBLE,
+		.bitrate = 10,
+		.hw_value = 0,
+		.hw_value_short = 0,
+	},
+	{
+		.flags = IEEE80211_RATE_SHORT_PREAMBLE,
+		.bitrate = 20,
+		.hw_value = 1,
+		.hw_value_short = 1,
+	},
+	{
+		.flags = IEEE80211_RATE_SHORT_PREAMBLE,
+		.bitrate = 55,
+		.hw_value = 2,
+		.hw_value_short = 2,
+	},
+	{
+		.flags = IEEE80211_RATE_SHORT_PREAMBLE,
+		.bitrate = 110,
+		.hw_value = 3,
+		.hw_value_short = 3,
+	},
+	{
+		.flags = 0,
+		.bitrate = 60,
+		.hw_value = 4,
+		.hw_value_short = 4,
+	},
+	{
+		.flags = 0,
+		.bitrate = 90,
+		.hw_value = 5,
+		.hw_value_short = 5,
+	},
+	{
+		.flags = 0,
+		.bitrate = 120,
+		.hw_value = 6,
+		.hw_value_short = 6,
+	},
+	{
+		.flags = 0,
+		.bitrate = 180,
+		.hw_value = 7,
+		.hw_value_short = 7,
+	},
+	{
+		.flags = 0,
+		.bitrate = 240,
+		.hw_value = 8,
+		.hw_value_short = 8,
+	},
+	{
+		.flags = 0,
+		.bitrate = 360,
+		.hw_value = 9,
+		.hw_value_short = 9,
+	},
+	{
+		.flags = 0,
+		.bitrate = 480,
+		.hw_value = 10,
+		.hw_value_short = 10,
+	},
+	{
+		.flags = 0,
+		.bitrate = 540,
+		.hw_value = 11,
+		.hw_value_short = 11,
+	},
+};
+
+static const UINT32 CipherSuites[] = {
+	WLAN_CIPHER_SUITE_WEP40,
+	WLAN_CIPHER_SUITE_WEP104,
+	WLAN_CIPHER_SUITE_TKIP,
+	WLAN_CIPHER_SUITE_CCMP,
+};
+
+/*
+========================================================================
+Routine Description:
+	UnRegister MAC80211 Module.
+
+Arguments:
+	pCB				- CFG80211 control block pointer
+	pNetDev			- Network device
+
+Return Value:
+	NONE
+
+Note:
+========================================================================
+*/
+VOID CFG80211OS_UnRegister(
+	IN VOID *pCB,
+	IN VOID *pNetDevOrg)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	struct net_device *pNetDev = (struct net_device *)pNetDevOrg;
+
+
+	/* unregister */
+	if (pCfg80211_CB->pCfg80211_Wdev != NULL)
+	{
+		DBGPRINT(RT_DEBUG_ERROR, ("80211> unregister/free wireless device\n"));
+
+		/*
+			Must unregister, or you will suffer problem when you change
+			regulatory domain by using iw.
+		*/
+		
+#ifdef RFKILL_HW_SUPPORT
+		wiphy_rfkill_stop_polling(pCfg80211_CB->pCfg80211_Wdev->wiphy);
+#endif /* RFKILL_HW_SUPPORT */
+		wiphy_unregister(pCfg80211_CB->pCfg80211_Wdev->wiphy);
+		wiphy_free(pCfg80211_CB->pCfg80211_Wdev->wiphy);
+		kfree(pCfg80211_CB->pCfg80211_Wdev);
+
+		if (pCfg80211_CB->pCfg80211_Channels != NULL)
+			kfree(pCfg80211_CB->pCfg80211_Channels);
+
+		if (pCfg80211_CB->pCfg80211_Rates != NULL)
+			kfree(pCfg80211_CB->pCfg80211_Rates);
+
+		pCfg80211_CB->pCfg80211_Wdev = NULL;
+		pCfg80211_CB->pCfg80211_Channels = NULL;
+		pCfg80211_CB->pCfg80211_Rates = NULL;
+
+		/* must reset to NULL; or kernel will panic in unregister_netdev */
+		pNetDev->ieee80211_ptr = NULL;
+		SET_NETDEV_DEV(pNetDev, NULL);
+	}
+
+	os_free_mem(NULL, pCfg80211_CB);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize wireless channel in 2.4GHZ and 5GHZ.
+
+Arguments:
+	pAd				- WLAN control block pointer
+	pWiphy			- WLAN PHY interface
+	pChannels		- Current channel info
+	pRates			- Current rate info
+
+Return Value:
+	TRUE			- init successfully
+	FALSE			- init fail
+
+Note:
+	TX Power related:
+
+	1. Suppose we can send power to 15dBm in the board.
+	2. A value 0x0 ~ 0x1F for a channel. We will adjust it based on 15dBm/
+		54Mbps. So if value == 0x07, the TX power of 54Mbps is 15dBm and
+		the value is 0x07 in the EEPROM.
+	3. Based on TX power value of 54Mbps/channel, adjust another value
+		0x0 ~ 0xF for other data rate. (-6dBm ~ +6dBm)
+
+	Other related factors:
+	1. TX power percentage from UI/users;
+	2. Maximum TX power limitation in the regulatory domain.
+========================================================================
+*/
+BOOLEAN CFG80211_SupBandInit(
+	IN VOID *pCB,
+	IN CFG80211_BAND *pBandInfo,
+	IN VOID *pWiphyOrg,
+	IN VOID *pChannelsOrg,
+	IN VOID *pRatesOrg)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg;
+	struct ieee80211_channel *pChannels = (struct ieee80211_channel *)pChannelsOrg;
+	struct ieee80211_rate *pRates = (struct ieee80211_rate *)pRatesOrg;
+	struct ieee80211_supported_band *pBand;
+	UINT32 NumOfChan, NumOfRate;
+	UINT32 IdLoop;
+	UINT32 CurTxPower;
+
+
+	/* sanity check */
+	if (pBandInfo->RFICType == 0)
+		pBandInfo->RFICType = RFIC_24GHZ | RFIC_5GHZ;
+
+	CFG80211DBG(RT_DEBUG_ERROR, ("80211> RFICType = %d\n",
+				pBandInfo->RFICType));
+
+	/* init */
+	if (pBandInfo->RFICType & RFIC_5GHZ)
+		NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ + CFG80211_NUM_OF_CHAN_5GHZ;
+	else
+		NumOfChan = CFG80211_NUM_OF_CHAN_2GHZ;
+
+	if (pBandInfo->FlgIsBMode == TRUE)
+		NumOfRate = 4;
+	else
+		NumOfRate = 4 + 8;
+
+	if (pChannels == NULL)
+	{
+		pChannels = kzalloc(sizeof(*pChannels) * NumOfChan, GFP_KERNEL);
+		if (!pChannels)
+		{
+			DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_channel allocation fail!\n"));
+			return FALSE;
+		}
+	}
+
+	CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of channel = %d\n",
+				CFG80211_NUM_OF_CHAN_5GHZ));
+
+	if (pRates == NULL)
+	{
+		pRates = kzalloc(sizeof(*pRates) * NumOfRate, GFP_KERNEL);
+		if (!pRates)
+		{
+			os_free_mem(NULL, pChannels);
+			DBGPRINT(RT_DEBUG_ERROR, ("80211> ieee80211_rate allocation fail!\n"));
+			return FALSE;
+		}
+	}
+
+	CFG80211DBG(RT_DEBUG_ERROR, ("80211> Number of rate = %d\n", NumOfRate));
+
+	/* get TX power */
+#ifdef SINGLE_SKU
+	CurTxPower = pBandInfo->DefineMaxTxPwr; /* dBm */
+#else
+	CurTxPower = 0; /* unknown */
+#endif /* SINGLE_SKU */
+
+	CFG80211DBG(RT_DEBUG_ERROR, ("80211> CurTxPower = %d dBm\n", CurTxPower));
+
+	/* init channel */
+	for(IdLoop=0; IdLoop<NumOfChan; IdLoop++)
+	{
+		pChannels[IdLoop].center_freq = \
+					ieee80211_channel_to_frequency(Cfg80211_Chan[IdLoop]);
+		pChannels[IdLoop].hw_value = IdLoop;
+
+		if (IdLoop < CFG80211_NUM_OF_CHAN_2GHZ)
+			pChannels[IdLoop].max_power = CurTxPower;
+		else
+			pChannels[IdLoop].max_power = CurTxPower;
+
+		pChannels[IdLoop].max_antenna_gain = 0xff;
+	}
+
+	/* init rate */
+	for(IdLoop=0; IdLoop<NumOfRate; IdLoop++)
+		memcpy(&pRates[IdLoop], &Cfg80211_SupRate[IdLoop], sizeof(*pRates));
+
+	pBand = &pCfg80211_CB->Cfg80211_bands[IEEE80211_BAND_2GHZ];
+	if (pBandInfo->RFICType & RFIC_24GHZ)
+	{
+		pBand->n_channels = CFG80211_NUM_OF_CHAN_2GHZ;
+		pBand->n_bitrates = NumOfRate;
+		pBand->channels = pChannels;
+		pBand->bitrates = pRates;
+
+#ifdef DOT11_N_SUPPORT
+		/* for HT, assign pBand->ht_cap */
+		pBand->ht_cap.ht_supported = true;
+		pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+					       IEEE80211_HT_CAP_SM_PS |
+					       IEEE80211_HT_CAP_SGI_40 |
+					       IEEE80211_HT_CAP_DSSSCCK40;
+		pBand->ht_cap.ampdu_factor = 3; /* 2 ^ 16 */
+		pBand->ht_cap.ampdu_density = pBandInfo->MpduDensity;
+
+		memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs));
+		CFG80211DBG(RT_DEBUG_ERROR,
+					("80211> TxStream = %d\n", pBandInfo->TxStream));
+
+		switch(pBandInfo->TxStream)
+		{
+			case 1:
+			default:
+				pBand->ht_cap.mcs.rx_mask[0] = 0xff;
+				break;
+
+			case 2:
+				pBand->ht_cap.mcs.rx_mask[0] = 0xff;
+				pBand->ht_cap.mcs.rx_mask[1] = 0xff;
+				break;
+
+			case 3:
+				pBand->ht_cap.mcs.rx_mask[0] = 0xff;
+				pBand->ht_cap.mcs.rx_mask[1] = 0xff;
+				pBand->ht_cap.mcs.rx_mask[2] = 0xff;
+				break;
+		}
+
+		pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+#endif /* DOT11_N_SUPPORT */
+
+		pWiphy->bands[IEEE80211_BAND_2GHZ] = pBand;
+	}
+	else
+	{
+		pWiphy->bands[IEEE80211_BAND_2GHZ] = NULL;
+		pBand->channels = NULL;
+		pBand->bitrates = NULL;
+	}
+
+	pBand = &pCfg80211_CB->Cfg80211_bands[IEEE80211_BAND_5GHZ];
+	if (pBandInfo->RFICType & RFIC_5GHZ)
+	{
+		pBand->n_channels = CFG80211_NUM_OF_CHAN_5GHZ;
+		pBand->n_bitrates = NumOfRate - 4;
+		pBand->channels = &pChannels[CFG80211_NUM_OF_CHAN_2GHZ];
+		pBand->bitrates = &pRates[4];
+
+		/* for HT, assign pBand->ht_cap */
+#ifdef DOT11_N_SUPPORT
+		/* for HT, assign pBand->ht_cap */
+		pBand->ht_cap.ht_supported = true;
+		pBand->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+					       IEEE80211_HT_CAP_SM_PS |
+					       IEEE80211_HT_CAP_SGI_40 |
+					       IEEE80211_HT_CAP_DSSSCCK40;
+		pBand->ht_cap.ampdu_factor = 3; /* 2 ^ 16 */
+		pBand->ht_cap.ampdu_density = pBandInfo->MpduDensity;
+
+		memset(&pBand->ht_cap.mcs, 0, sizeof(pBand->ht_cap.mcs));
+		switch(pBandInfo->RxStream)
+		{
+			case 1:
+			default:
+				pBand->ht_cap.mcs.rx_mask[0] = 0xff;
+				break;
+
+			case 2:
+				pBand->ht_cap.mcs.rx_mask[0] = 0xff;
+				pBand->ht_cap.mcs.rx_mask[1] = 0xff;
+				break;
+
+			case 3:
+				pBand->ht_cap.mcs.rx_mask[0] = 0xff;
+				pBand->ht_cap.mcs.rx_mask[1] = 0xff;
+				pBand->ht_cap.mcs.rx_mask[2] = 0xff;
+				break;
+		}
+
+		pBand->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+#endif /* DOT11_N_SUPPORT */
+
+		pWiphy->bands[IEEE80211_BAND_5GHZ] = pBand;
+	}
+	else
+	{
+		pWiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
+		pBand->channels = NULL;
+		pBand->bitrates = NULL;
+	}
+
+	pCfg80211_CB->pCfg80211_Channels = pChannels;
+	pCfg80211_CB->pCfg80211_Rates = pRates;
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Re-Initialize wireless channel/PHY in 2.4GHZ and 5GHZ.
+
+Arguments:
+	pCB				- CFG80211 control block pointer
+	pBandInfo		- Band information
+
+Return Value:
+	TRUE			- re-init successfully
+	FALSE			- re-init fail
+
+Note:
+	CFG80211_SupBandInit() is called in xx_probe().
+	But we do not have complete chip information in xx_probe() so we
+	need to re-init bands in xx_open().
+========================================================================
+*/
+BOOLEAN CFG80211OS_SupBandReInit(
+	IN VOID *pCB,
+	IN CFG80211_BAND *pBandInfo)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	struct wiphy *pWiphy;
+
+
+	if ((pCfg80211_CB == NULL) || (pCfg80211_CB->pCfg80211_Wdev == NULL))
+		return FALSE;
+
+	pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy;
+
+	if (pWiphy != NULL)
+	{
+		CFG80211DBG(RT_DEBUG_ERROR, ("80211> re-init bands...\n"));
+
+		/* re-init bands */
+		CFG80211_SupBandInit(pCfg80211_CB, pBandInfo, pWiphy,
+							pCfg80211_CB->pCfg80211_Channels,
+							pCfg80211_CB->pCfg80211_Rates);
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32))
+		/* re-init PHY */
+		pWiphy->rts_threshold = pBandInfo->RtsThreshold;
+		pWiphy->frag_threshold = pBandInfo->FragmentThreshold;
+		pWiphy->retry_short = pBandInfo->RetryMaxCnt & 0xff;
+		pWiphy->retry_long = (pBandInfo->RetryMaxCnt & 0xff00)>>8;
+#endif /* LINUX_VERSION_CODE */
+
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Hint to the wireless core a regulatory domain from driver.
+
+Arguments:
+	pAd				- WLAN control block pointer
+	pCountryIe		- pointer to the country IE
+	CountryIeLen	- length of the country IE
+
+Return Value:
+	NONE
+
+Note:
+	Must call the function in kernel thread.
+========================================================================
+*/
+VOID CFG80211OS_RegHint(
+	IN VOID *pCB,
+	IN UCHAR *pCountryIe,
+	IN ULONG CountryIeLen)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+
+
+	CFG80211DBG(RT_DEBUG_ERROR,
+			("crda> regulatory domain hint: %c%c\n",
+			pCountryIe[0], pCountryIe[1]));
+
+	if ((pCfg80211_CB->pCfg80211_Wdev == NULL) || (pCountryIe == NULL))
+	{
+		CFG80211DBG(RT_DEBUG_ERROR, ("crda> regulatory domain hint not support!\n"));
+		return;
+	}
+
+	/* hints a country IE as a regulatory domain "without" channel/power info. */
+/*	regulatory_hint(pCfg80211_CB->pMac80211_Hw->wiphy, pCountryIe); */
+	regulatory_hint(pCfg80211_CB->pCfg80211_Wdev->wiphy, (const char *)pCountryIe);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Hint to the wireless core a regulatory domain from country element.
+
+Arguments:
+	pAdCB			- WLAN control block pointer
+	pCountryIe		- pointer to the country IE
+	CountryIeLen	- length of the country IE
+
+Return Value:
+	NONE
+
+Note:
+	Must call the function in kernel thread.
+========================================================================
+*/
+VOID CFG80211OS_RegHint11D(
+	IN VOID *pCB,
+	IN UCHAR *pCountryIe,
+	IN ULONG CountryIeLen)
+{
+	/* no regulatory_hint_11d() in 2.6.32 */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32))
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+
+
+	if ((pCfg80211_CB->pCfg80211_Wdev == NULL) || (pCountryIe == NULL))
+	{
+		CFG80211DBG(RT_DEBUG_ERROR, ("crda> regulatory domain hint not support!\n"));
+		return;
+	}
+
+	CFG80211DBG(RT_DEBUG_ERROR,
+				("crda> regulatory domain hint: %c%c\n",
+				pCountryIe[0], pCountryIe[1]));
+
+	/*
+		hints a country IE as a regulatory domain "with" channel/power info.
+		but if you use regulatory_hint(), it only hint "regulatory domain".
+	*/
+/*	regulatory_hint_11d(pCfg80211_CB->pMac80211_Hw->wiphy, pCountryIe, CountryIeLen); */
+	regulatory_hint_11d(pCfg80211_CB->pCfg80211_Wdev->wiphy, pCountryIe, CountryIeLen);
+#endif /* LINUX_VERSION_CODE */
+}
+
+
+BOOLEAN CFG80211OS_BandInfoGet(
+	IN VOID *pCB,
+	IN VOID *pWiphyOrg,
+	OUT VOID **ppBand24,
+	OUT VOID **ppBand5)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg;
+
+
+	if (pWiphy == NULL)
+	{
+		if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL))
+			pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy;
+	}
+
+	if (pWiphy == NULL)
+		return FALSE;
+
+	*ppBand24 = pWiphy->bands[IEEE80211_BAND_2GHZ];
+	*ppBand5 = pWiphy->bands[IEEE80211_BAND_5GHZ];
+	return TRUE;
+}
+
+
+UINT32 CFG80211OS_ChanNumGet(
+	IN VOID						*pCB,
+	IN VOID						*pWiphyOrg,
+	IN UINT32					IdBand)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg;
+
+
+	if (pWiphy == NULL)
+	{
+		if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL))
+			pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy;
+	}
+
+	if (pWiphy == NULL)
+		return 0;
+
+	if (pWiphy->bands[IdBand] != NULL)
+		return pWiphy->bands[IdBand]->n_channels;
+
+	return 0;
+}
+
+
+BOOLEAN CFG80211OS_ChanInfoGet(
+	IN VOID						*pCB,
+	IN VOID						*pWiphyOrg,
+	IN UINT32					IdBand,
+	IN UINT32					IdChan,
+	OUT UINT32					*pChanId,
+	OUT UINT32					*pPower,
+	OUT BOOLEAN					*pFlgIsRadar)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	struct wiphy *pWiphy = (struct wiphy *)pWiphyOrg;
+	struct ieee80211_supported_band *pSband;
+	struct ieee80211_channel *pChan;
+
+
+	if (pWiphy == NULL)
+	{
+		if ((pCfg80211_CB != NULL) && (pCfg80211_CB->pCfg80211_Wdev != NULL))
+			pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy;
+	}
+
+	if (pWiphy == NULL)
+		return FALSE;
+
+	pSband = pWiphy->bands[IdBand];
+	pChan = &pSband->channels[IdChan];
+
+	*pChanId = ieee80211_frequency_to_channel(pChan->center_freq);
+
+	if (pChan->flags & IEEE80211_CHAN_DISABLED)
+	{
+		CFG80211DBG(RT_DEBUG_ERROR,
+					("Chan %03d (frq %d):\tnot allowed!\n",
+					(*pChanId), pChan->center_freq));
+		return FALSE;
+	}
+
+	*pPower = pChan->max_power;
+
+	if (pChan->flags & IEEE80211_CHAN_RADAR)
+		*pFlgIsRadar = TRUE;
+	else
+		*pFlgIsRadar = FALSE;
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize a channel information used in scan inform.
+
+Arguments:
+
+Return Value:
+	TRUE		- Successful
+	FALSE		- Fail
+
+Note:
+========================================================================
+*/
+BOOLEAN CFG80211OS_ChanInfoInit(
+	IN VOID						*pCB,
+	IN UINT32					InfoIndex,
+	IN UCHAR					ChanId,
+	IN UCHAR					MaxTxPwr,
+	IN BOOLEAN					FlgIsNMode,
+	IN BOOLEAN					FlgIsBW20M)
+{
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	struct ieee80211_channel *pChan;
+
+
+	if (InfoIndex >= MAX_NUM_OF_CHANNELS)
+		return FALSE;
+
+	pChan = (struct ieee80211_channel *)&(pCfg80211_CB->ChanInfo[InfoIndex]);
+	memset(pChan, 0, sizeof(*pChan));
+
+	if (ChanId > 14)
+		pChan->band = IEEE80211_BAND_5GHZ;
+	else
+		pChan->band = IEEE80211_BAND_2GHZ;
+
+	pChan->center_freq = ieee80211_channel_to_frequency(ChanId);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32))
+	if (FlgIsNMode == TRUE)
+	{
+		if (FlgIsBW20M == TRUE)
+			pChan->max_bandwidth = 20; /* 20MHz */
+		else
+			pChan->max_bandwidth = 40; /* 40MHz */
+	}
+	else
+		pChan->max_bandwidth = 5; /* 5MHz for non-HT device */
+#endif /* LINUX_VERSION_CODE */
+
+	/* no use currently in 2.6.30 */
+/*	if (ieee80211_is_beacon(((struct ieee80211_mgmt *)pFrame)->frame_control)) */
+/*		pChan->beacon_found = 1; */
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Inform us that a scan is got.
+
+Arguments:
+	pAdCB				- WLAN control block pointer
+
+Return Value:
+	NONE
+
+Note:
+	Call RT_CFG80211_SCANNING_INFORM, not CFG80211_Scaning
+========================================================================
+*/
+VOID CFG80211OS_Scaning(
+	IN VOID						*pCB,
+	IN UINT32					ChanId,
+	IN UCHAR					*pFrame,
+	IN UINT32					FrameLen,
+	IN INT32					RSSI,
+	IN BOOLEAN					FlgIsNMode,
+	IN UINT8					BW)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
+#ifdef CONFIG_STA_SUPPORT
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+	UINT32 IdChan;
+	UINT32 CenFreq;
+
+
+	/* get channel information */
+	CenFreq = ieee80211_channel_to_frequency(ChanId);
+
+	for(IdChan=0; IdChan<MAX_NUM_OF_CHANNELS; IdChan++)
+	{
+		if (pCfg80211_CB->ChanInfo[IdChan].center_freq == CenFreq)
+			break;
+	}
+	if (IdChan >= MAX_NUM_OF_CHANNELS)
+	{
+		DBGPRINT(RT_DEBUG_ERROR, ("80211> Can not find any chan info!\n"));
+		return;
+	}
+
+	/* inform 80211 a scan is got */
+	/* we can use cfg80211_inform_bss in 2.6.31, it is easy more than the one */
+	/* in cfg80211_inform_bss_frame(), it will memcpy pFrame but pChan */
+	cfg80211_inform_bss_frame(pCfg80211_CB->pCfg80211_Wdev->wiphy,
+								&pCfg80211_CB->ChanInfo[IdChan],
+								(struct ieee80211_mgmt *)pFrame,
+								FrameLen,
+								RSSI,
+								GFP_ATOMIC);
+
+	CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_inform_bss_frame\n"));
+#endif /* CONFIG_STA_SUPPORT */
+#endif /* LINUX_VERSION_CODE */
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Inform us that scan ends.
+
+Arguments:
+	pAdCB			- WLAN control block pointer
+	FlgIsAborted	- 1: scan is aborted
+
+Return Value:
+	NONE
+
+Note:
+========================================================================
+*/
+VOID CFG80211OS_ScanEnd(
+	IN VOID *pCB,
+	IN BOOLEAN FlgIsAborted)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30))
+#ifdef CONFIG_STA_SUPPORT
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+
+
+	CFG80211DBG(RT_DEBUG_ERROR, ("80211> cfg80211_scan_done\n"));
+	cfg80211_scan_done(pCfg80211_CB->pCfg80211_ScanReq, FlgIsAborted);
+#endif /* CONFIG_STA_SUPPORT */
+#endif /* LINUX_VERSION_CODE */
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Inform CFG80211 about association status.
+
+Arguments:
+	pAdCB			- WLAN control block pointer
+	pBSSID			- the BSSID of the AP
+	pReqIe			- the element list in the association request frame
+	ReqIeLen		- the request element length
+	pRspIe			- the element list in the association response frame
+	RspIeLen		- the response element length
+	FlgIsSuccess	- 1: success; otherwise: fail
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+void CFG80211OS_ConnectResultInform(
+	IN VOID *pCB,
+	IN UCHAR *pBSSID,
+	IN UCHAR *pReqIe,
+	IN UINT32 ReqIeLen,
+	IN UCHAR *pRspIe,
+	IN UINT32 RspIeLen,
+	IN UCHAR FlgIsSuccess)
+{
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32))
+	CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pCB;
+
+
+	if ((pCfg80211_CB->pCfg80211_Wdev->netdev == NULL) || (pBSSID == NULL))
+		return;
+
+	if (FlgIsSuccess)
+	{
+		cfg80211_connect_result(pCfg80211_CB->pCfg80211_Wdev->netdev,
+								pBSSID,
+								pReqIe,
+								ReqIeLen,
+								pRspIe,
+								RspIeLen,
+								WLAN_STATUS_SUCCESS,
+								GFP_KERNEL);
+	}
+	else
+	{
+		cfg80211_connect_result(pCfg80211_CB->pCfg80211_Wdev->netdev,
+								pBSSID,
+								NULL, 0, NULL, 0,
+								WLAN_STATUS_UNSPECIFIED_FAILURE,
+								GFP_KERNEL);
+	}
+#endif /* LINUX_VERSION_CODE */
+}
+#endif /* RT_CFG80211_SUPPORT */
+
+
+/*
+========================================================================
+Routine Description:
+	Flush a data cache line.
+
+Arguments:
+	AddrStart		- the start address
+	Size			- memory size
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsDCacheFlush(
+	IN ULONG AddrStart,
+	IN ULONG Size)
+{
+	RTMP_UTIL_DCACHE_FLUSH(AddrStart, Size);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Assign private data pointer to the network interface.
+
+Arguments:
+	pDev			- the device
+	pPriv			- the pointer
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsSetNetDevPriv(VOID *pDev, VOID *pPriv)
+{
+	DEV_PRIV_INFO *pDevInfo = NULL;
+
+
+	pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev);
+	if (pDevInfo == NULL)
+	{
+		os_alloc_mem(NULL, (UCHAR **)&pDevInfo, sizeof(DEV_PRIV_INFO));
+		if (pDevInfo == NULL)
+			return;
+	}
+
+	pDevInfo->pPriv = (VOID *)pPriv;
+	pDevInfo->priv_flags = 0;
+
+	_RTMP_OS_NETDEV_SET_PRIV((PNET_DEV) pDev, pDevInfo);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get private data pointer from the network interface.
+
+Arguments:
+	pDev			- the device
+	pPriv			- the pointer
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID *RtmpOsGetNetDevPriv(VOID *pDev)
+{
+	DEV_PRIV_INFO *pDevInfo = NULL;
+
+
+	pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev);
+	if (pDevInfo != NULL)
+		return pDevInfo->pPriv;
+	return NULL;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get private flags from the network interface.
+
+Arguments:
+	pDev			- the device
+
+Return Value:
+	pPriv			- the pointer
+
+Note:
+========================================================================
+*/
+USHORT RtmpDevPrivFlagsGet(VOID *pDev)
+{
+
+	DEV_PRIV_INFO *pDevInfo = NULL;
+
+
+	pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev);
+	if (pDevInfo != NULL)
+		return pDevInfo->priv_flags;
+	return 0;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get private flags from the network interface.
+
+Arguments:
+	pDev			- the device
+
+Return Value:
+	pPriv			- the pointer
+
+Note:
+========================================================================
+*/
+VOID RtmpDevPrivFlagsSet(VOID *pDev, USHORT PrivFlags)
+{
+	DEV_PRIV_INFO *pDevInfo = NULL;
+
+
+	pDevInfo = (DEV_PRIV_INFO *) _RTMP_OS_NETDEV_GET_PRIV((PNET_DEV) pDev);
+	if (pDevInfo != NULL)
+		pDevInfo->priv_flags = PrivFlags;
+}
+
+
+#ifdef WIDI_SUPPORT
+#ifdef CONFIG_STA_SUPPORT
+INT RtmpOSWidiNotify(
+	IN PNET_DEV pNetDev, 
+	IN PUCHAR buff,
+	IN INT len, 
+	IN ULONG type)
+{
+	struct sk_buff *skb = NULL;
+	
+	skb = dev_alloc_skb(len + 2);
+	
+	if (!skb) 
+	{
+		DBGPRINT(RT_DEBUG_ERROR,( "%s: failed to allocate sk_buff for notification\n", pNetDev->name));		
+		return -ENOMEM;		
+	} 
+	else 
+	{		
+		skb_reserve(skb, 2);		
+		memcpy(skb_put(skb, len), buff, len);		
+		skb->len = len;
+		skb->dev = pNetDev;
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21))
+		skb->mac.raw = skb->data;
+#else
+		skb_set_mac_header(skb, 0);
+#endif
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->pkt_type = PACKET_OTHERHOST;
+		skb->protocol = htons(ETH_P_WIDI_NOTIF);
+		memset(skb->cb, 0, sizeof(skb->cb));		
+#if 0
+		hex_dump("data", skb->data, skb->len);
+#endif
+		netif_rx(skb);
+	}
+	return 0;
+}
+#endif /* CONFIG_STA_SUPPORT */
+#endif /*WIDI_SUPPORT */
+
+
+#ifdef OS_ABL_FUNC_SUPPORT
+/*
+========================================================================
+Routine Description:
+	Change/Recover file UID/GID.
+
+Arguments:
+	pOSFSInfoOrg	- the file
+	bSet			- Change (TRUE) or Recover (FALSE)
+
+Return Value:
+	None
+
+Note:
+	rt_linux.h, not rt_drv.h
+========================================================================
+*/
+void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet)
+{
+	OS_FS_INFO *pOSFSInfo;
+
+	if (bSet == TRUE) {
+		os_alloc_mem(NULL, (UCHAR **) & (pOSFSInfoOrg->pContent),
+			     sizeof (OS_FS_INFO));
+		if (pOSFSInfoOrg->pContent == NULL) {
+			DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc file info fail!\n", __FUNCTION__));
+			return;
+		} else
+			memset(pOSFSInfoOrg->pContent, 0, sizeof (OS_FS_INFO));
+	}
+
+	pOSFSInfo = (OS_FS_INFO *) (pOSFSInfoOrg->pContent);
+	if (pOSFSInfo == NULL) {
+		DBGPRINT(RT_DEBUG_ERROR, ("%s: pOSFSInfo == NULL!\n", __FUNCTION__));
+		return;
+	}
+
+	__RtmpOSFSInfoChange(pOSFSInfo, bSet);
+
+	if (bSet == FALSE) {
+		if (pOSFSInfoOrg->pContent != NULL) {
+			os_free_mem(NULL, pOSFSInfoOrg->pContent);
+			pOSFSInfoOrg->pContent = NULL;
+		}
+	}
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Activate a tasklet.
+
+Arguments:
+	pTasklet		- the tasklet
+
+Return Value:
+	TRUE or FALSE
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsTaskletSche(RTMP_NET_TASK_STRUCT *pTasklet)
+{
+	if (pTasklet->pContent == NULL)
+		return FALSE;
+
+#ifdef WORKQUEUE_BH
+	schedule_work((struct work_struct *)(pTasklet->pContent));
+#else
+	tasklet_hi_schedule((OS_NET_TASK_STRUCT *) (pTasklet->pContent));
+#endif /* WORKQUEUE_BH */
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize a tasklet.
+
+Arguments:
+	pTasklet		- the tasklet
+
+Return Value:
+	TRUE or FALSE
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsTaskletInit(
+	RTMP_NET_TASK_STRUCT *pTasklet,
+	VOID (*pFunc) (unsigned long data),
+	ULONG Data,
+	LIST_HEADER *pTaskletList)
+{
+#ifdef WORKQUEUE_BH
+	if (RTMP_OS_Alloc_RscOnly(pTasklet, sizeof (struct work_struct)) == FALSE)
+		return FALSE;
+
+	INIT_WORK((struct work_struct *)(pTasklet->pContent), pFunc);
+#else
+
+	if (RTMP_OS_Alloc_RscOnly(pTasklet, sizeof (OS_NET_TASK_STRUCT)) == FALSE)
+		return FALSE;
+
+	tasklet_init((OS_NET_TASK_STRUCT *) (pTasklet->pContent), pFunc, Data);
+#endif /* WORKQUEUE_BH */
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Delete a tasklet.
+
+Arguments:
+	pTasklet		- the tasklet
+
+Return Value:
+	TRUE or FALSE
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsTaskletKill(RTMP_NET_TASK_STRUCT *pTasklet)
+{
+	if (pTasklet->pContent != NULL) {
+#ifndef WORKQUEUE_BH
+		tasklet_kill((OS_NET_TASK_STRUCT *) (pTasklet->pContent));
+#endif /* WORKQUEUE_BH */
+
+		os_free_mem(NULL, pTasklet->pContent);
+		pTasklet->pContent = NULL;
+	}
+
+	return TRUE;
+}
+
+
+VOID RtmpOsTaskletDataAssign(RTMP_NET_TASK_STRUCT *pTasklet, ULONG Data)
+{
+#ifndef WORKQUEUE_BH
+	if (pTasklet->pContent != NULL)
+		((OS_NET_TASK_STRUCT *) (pTasklet->pContent))->data = Data;
+#endif /* WORKQUEUE_BH */
+}
+
+
+INT32 RtmpOsTaskIsKilled(RTMP_OS_TASK *pTaskOrg)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask == NULL)
+		return 1;
+	return pTask->task_killed;
+}
+
+
+VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTaskOrg)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask == NULL)
+		return;
+
+#ifdef KTHREAD_SUPPORT
+	WAKE_UP(pTask);
+#else
+	RTMP_SEM_EVENT_UP(&pTask->taskSema);
+#endif
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Check if the task is legal.
+
+Arguments:
+	pPkt			- the packet
+	pDev			- the device
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsCheckTaskLegality(RTMP_OS_TASK *pTaskOrg)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (!pTask)
+		return FALSE;
+
+#ifdef KTHREAD_SUPPORT
+	if (pTask->kthread_task == NULL)
+#else
+	CHECK_PID_LEGALITY(pTask->taskPID);
+	else
+#endif
+	return FALSE;
+
+	return TRUE;
+}
+
+
+/* timeout -- ms */
+VOID RTMP_SetPeriodicTimer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout)
+{
+	OS_NDIS_MINIPORT_TIMER *pTimer;
+
+	pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent);
+	if (pTimer)
+		__RTMP_SetPeriodicTimer(pTimer, timeout);
+}
+
+
+/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
+VOID RTMP_OS_Init_Timer(
+	VOID *pReserved,
+	NDIS_MINIPORT_TIMER *pTimerOrg,
+	TIMER_FUNCTION function,
+	PVOID data,
+	LIST_HEADER *pTimerList)
+{
+	OS_NDIS_MINIPORT_TIMER *pTimer;
+
+	if (RTMP_OS_Alloc_RscOnly(pTimerOrg, sizeof (OS_NDIS_MINIPORT_TIMER)) == FALSE)
+		return;
+
+	pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent);
+	if (pTimer)
+		__RTMP_OS_Init_Timer(pReserved, pTimer, function, data);
+}
+
+
+VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout)
+{
+	OS_NDIS_MINIPORT_TIMER *pTimer;
+
+	 pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent);
+
+	if (pTimer) {
+		if (timer_pending(pTimer))
+			return;
+
+		__RTMP_OS_Add_Timer(pTimer, timeout);
+	}
+} 
+
+
+VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, ULONG timeout)
+{
+	OS_NDIS_MINIPORT_TIMER *pTimer;
+
+	pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent);
+	if (pTimer)
+		__RTMP_OS_Mod_Timer(pTimer, timeout);
+}
+
+
+VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled)
+{
+	OS_NDIS_MINIPORT_TIMER *pTimer;
+
+	pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent);
+	if (pTimer)
+		__RTMP_OS_Del_Timer(pTimer, pCancelled);
+}
+
+
+VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg)
+{
+	OS_NDIS_MINIPORT_TIMER *pTimer;
+
+	pTimer = (OS_NDIS_MINIPORT_TIMER *) (pTimerOrg->pContent);
+	if (pTimer) {
+		__RTMP_OS_Release_Timer(pTimer);
+
+		os_free_mem(NULL, pTimer);
+		pTimerOrg->pContent = NULL;
+	}
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Allocate a OS resource.
+
+Arguments:
+	pAd				- WLAN control block pointer
+	pRsc			- the resource
+	RscLen			- resource length
+
+Return Value:
+	TRUE or FALSE
+
+Note:
+========================================================================
+*/
+BOOLEAN RTMP_OS_Alloc_Rsc(
+	LIST_HEADER *pRscList,
+	VOID *pRscSrc,
+	UINT32 RscLen)
+{
+	OS_RSTRUC *pRsc = (OS_RSTRUC *) pRscSrc;
+
+	if (pRsc->pContent == NULL) {
+		/* new entry */
+		os_alloc_mem(NULL, (UCHAR **) & (pRsc->pContent), RscLen);
+		if (pRsc->pContent == NULL) {
+			DBGPRINT(RT_DEBUG_ERROR,
+				 ("%s: alloc timer fail!\n", __FUNCTION__));
+			return FALSE;
+		} else {
+			LIST_RESOURCE_OBJ_ENTRY *pObj;
+
+			/* allocate resource record entry */
+			os_alloc_mem(NULL, (UCHAR **) & (pObj),
+				     sizeof (LIST_RESOURCE_OBJ_ENTRY));
+			if (pObj == NULL) {
+				DBGPRINT(RT_DEBUG_ERROR,
+					 ("%s: alloc timer obj fail!\n",
+					  __FUNCTION__));
+				os_free_mem(NULL, pRsc->pContent);
+				pRsc->pContent = NULL;
+				return FALSE;
+			} else {
+				memset(pRsc->pContent, 0, RscLen);
+				pObj->pRscObj = (VOID *) pRsc;
+
+				OS_SEM_LOCK(&UtilSemLock);
+				insertTailList(pRscList, (LIST_ENTRY *) pObj);
+				OS_SEM_UNLOCK(&UtilSemLock);
+			}
+		}
+	}
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Allocate a OS resource.
+
+Arguments:
+	pAd				- WLAN control block pointer
+	pRsc			- the resource
+	RscLen			- resource length
+
+Return Value:
+	TRUE or FALSE
+
+Note:
+========================================================================
+*/
+BOOLEAN RTMP_OS_Alloc_RscOnly(VOID *pRscSrc, UINT32 RscLen)
+{
+	OS_RSTRUC *pRsc = (OS_RSTRUC *) pRscSrc;
+
+	if (pRsc->pContent == NULL) {
+		/* new entry */
+		os_alloc_mem(NULL, (UCHAR **) & (pRsc->pContent), RscLen);
+		if (pRsc->pContent == NULL) {
+			DBGPRINT(RT_DEBUG_ERROR,
+				 ("%s: alloc timer fail!\n", __FUNCTION__));
+			return FALSE;
+		}
+		memset(pRsc->pContent, 0, RscLen);
+	}
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Remove a OS resource.
+
+Arguments:
+	pAd				- WLAN control block pointer
+	pRsc			- the resource
+
+Return Value:
+	TRUE or FALSE
+
+Note:
+========================================================================
+*/
+BOOLEAN RTMP_OS_Remove_Rsc(
+	LIST_HEADER *pRscList,
+	VOID *pRscSrc)
+{
+	LIST_RESOURCE_OBJ_ENTRY *pObj;
+	OS_RSTRUC *pRscHead, *pRsc, *pRscRev = (OS_RSTRUC *) pRscSrc;
+	pRscHead = NULL;
+
+	OS_SEM_LOCK(&UtilSemLock);
+	while(TRUE)
+	{
+		pObj = (LIST_RESOURCE_OBJ_ENTRY *) removeHeadList(pRscList);
+		if (pRscHead == NULL)
+			pRscHead = pObj->pRscObj; /* backup first entry */
+		else if (((ULONG)pRscHead) == ((ULONG)(pObj->pRscObj)))
+			break; /* has searched all entries */
+
+		pRsc = (OS_RSTRUC *) (pObj->pRscObj);
+		if ((ULONG)pRsc == (ULONG)pRscRev)
+			break; /* find it */
+
+		/* re-insert it */
+		insertTailList(pRscList, (LIST_ENTRY *) pObj);
+	}
+	OS_SEM_UNLOCK(&UtilSemLock);
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Free all timers.
+
+Arguments:
+	pAd				- WLAN control block pointer
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RTMP_OS_Free_Rscs(LIST_HEADER *pRscList)
+{
+	LIST_RESOURCE_OBJ_ENTRY *pObj;
+	OS_RSTRUC *pRsc;
+
+	OS_SEM_LOCK(&UtilSemLock);
+	while (TRUE) {
+		pObj = (LIST_RESOURCE_OBJ_ENTRY *) removeHeadList(pRscList);
+		if (pObj == NULL)
+			break;
+		pRsc = (OS_RSTRUC *) (pObj->pRscObj);
+
+		if (pRsc->pContent != NULL) {
+			/* free the timer memory */
+			os_free_mem(NULL, pRsc->pContent);
+			pRsc->pContent = NULL;
+		} else {
+			/*
+			   The case is possible because some timers are released during
+			   the driver life time, EX: we will release some timers in
+			   MacTableDeleteEntry().
+			   But we do not recommend the behavior, i.e. not to release
+			   timers in the driver life time; Or we can not cancel the
+			   timer for timer preemption problem.
+			 */
+		}
+
+		os_free_mem(NULL, pObj);	/* free the timer record entry */
+	}
+	OS_SEM_UNLOCK(&UtilSemLock);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Allocate a kernel task.
+
+Arguments:
+	pTask			- the task
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOSTaskAlloc(RTMP_OS_TASK *pTask, LIST_HEADER *pTaskList)
+{
+	if (RTMP_OS_Alloc_RscOnly(pTask, sizeof (OS_TASK)) == FALSE) {
+		DBGPRINT(RT_DEBUG_ERROR,
+			 ("%s: alloc task fail!\n", __FUNCTION__));
+		return FALSE;	/* allocate fail */
+	}
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Free a kernel task.
+
+Arguments:
+	pTask			- the task
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOSTaskFree(RTMP_OS_TASK *pTaskOrg)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask != NULL) {
+		os_free_mem(NULL, pTask);
+		pTaskOrg->pContent = NULL;
+	}
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Kill a kernel task.
+
+Arguments:
+	pTaskOrg		- the task
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTaskOrg)
+{
+	OS_TASK *pTask;
+	NDIS_STATUS Status;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask != NULL) {
+		Status = __RtmpOSTaskKill(pTask);
+		RtmpOSTaskFree(pTaskOrg);
+		return Status;
+	}
+
+	return NDIS_STATUS_FAILURE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Notify kernel the task exit.
+
+Arguments:
+	pTaskOrg		- the task
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTaskOrg)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask == NULL)
+		return 0;
+	return __RtmpOSTaskNotifyToExit(pTask);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Customize the task.
+
+Arguments:
+	pTaskOrg		- the task
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOSTaskCustomize(RTMP_OS_TASK *pTaskOrg)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask)
+		__RtmpOSTaskCustomize(pTask);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Activate a kernel task.
+
+Arguments:
+	pTaskOrg		- the task
+	fn				- task handler
+	arg				- task input argument
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+NDIS_STATUS RtmpOSTaskAttach(
+	RTMP_OS_TASK *pTaskOrg,
+	RTMP_OS_TASK_CALLBACK fn,
+	ULONG arg)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask == NULL)
+		return NDIS_STATUS_FAILURE;
+	return __RtmpOSTaskAttach(pTask, fn, arg);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize a kernel task.
+
+Arguments:
+	pTaskOrg		- the task
+	pTaskName		- task name
+	pPriv			- task input argument
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+NDIS_STATUS RtmpOSTaskInit(
+	RTMP_OS_TASK *pTaskOrg,
+	PSTRING pTaskName,
+	VOID *pPriv,
+	LIST_HEADER *pTaskList,
+	LIST_HEADER *pSemList)
+{
+	OS_TASK *pTask;
+
+	if (RtmpOSTaskAlloc(pTaskOrg, pTaskList) == FALSE)
+		return NDIS_STATUS_FAILURE;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask == NULL)
+		return NDIS_STATUS_FAILURE;
+
+	return __RtmpOSTaskInit(pTask, pTaskName, pPriv, pSemList);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Wait for a event in the task.
+
+Arguments:
+	pAd				- WLAN control block pointer
+	pTaskOrg		- the task
+
+Return Value:
+	TRUE
+	FALSE
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOSTaskWait(VOID *pReserved, RTMP_OS_TASK *pTaskOrg, INT32 *pStatus)
+{
+	OS_TASK *pTask;
+
+	pTask = (OS_TASK *) (pTaskOrg->pContent);
+	if (pTask == NULL)
+		return FALSE;
+
+	return __RtmpOSTaskWait(pReserved, pTask, pStatus);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get private data for the task.
+
+Arguments:
+	pTaskOrg		- the task
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID *RtmpOsTaskDataGet(RTMP_OS_TASK *pTaskOrg)
+{
+	if (pTaskOrg->pContent == NULL)
+		return NULL;
+
+	return (((OS_TASK *) (pTaskOrg->pContent))->priv);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Allocate a lock.
+
+Arguments:
+	pLock			- the lock
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsAllocateLock(NDIS_SPIN_LOCK *pLock, LIST_HEADER *pLockList)
+{
+	if (RTMP_OS_Alloc_RscOnly(pLock, sizeof (OS_NDIS_SPIN_LOCK)) == FALSE) {
+		DBGPRINT(RT_DEBUG_ERROR,
+			 ("%s: alloc lock fail!\n", __FUNCTION__));
+		return FALSE;	/* allocate fail */
+	}
+
+	OS_NdisAllocateSpinLock(pLock->pContent);
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Free a lock.
+
+Arguments:
+	pLockOrg		- the lock
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsFreeSpinLock(NDIS_SPIN_LOCK *pLockOrg)
+{
+	/* we will free all locks memory in RTMP_OS_FREE_LOCK() */
+	OS_NDIS_SPIN_LOCK *pLock;
+
+	pLock = (OS_NDIS_MINIPORT_TIMER *) (pLockOrg->pContent);
+	if (pLock != NULL) {
+		OS_NdisFreeSpinLock(pLock);
+
+		os_free_mem(NULL, pLock);
+		pLockOrg->pContent = NULL;
+	}
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Spin lock bh.
+
+Arguments:
+	pLockOrg		- the lock
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsSpinLockBh(NDIS_SPIN_LOCK *pLockOrg)
+{
+	OS_NDIS_SPIN_LOCK *pLock;
+
+	pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent);
+	if (pLock != NULL) {
+		OS_SEM_LOCK(pLock);
+	} else
+		printk("lock> warning! the lock was freed!\n");
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Spin unlock bh.
+
+Arguments:
+	pLockOrg		- the lock
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsSpinUnLockBh(NDIS_SPIN_LOCK *pLockOrg)
+{
+	OS_NDIS_SPIN_LOCK *pLock;
+
+	pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent);
+	if (pLock != NULL) {
+		OS_SEM_UNLOCK(pLock);
+	} else
+		printk("lock> warning! the lock was freed!\n");
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Interrupt lock.
+
+Arguments:
+	pLockOrg		- the lock
+	pIrqFlags		- the lock flags
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsIntLock(NDIS_SPIN_LOCK *pLockOrg, ULONG *pIrqFlags)
+{
+	OS_NDIS_SPIN_LOCK *pLock;
+
+	pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent);
+	if (pLock != NULL) {
+		OS_INT_LOCK(pLock, *pIrqFlags);
+	} else
+		printk("lock> warning! the lock was freed!\n");
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Interrupt unlock.
+
+Arguments:
+	pLockOrg		- the lock
+	IrqFlags		- the lock flags
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsIntUnLock(NDIS_SPIN_LOCK *pLockOrg, ULONG IrqFlags)
+{
+	OS_NDIS_SPIN_LOCK *pLock;
+
+	pLock = (OS_NDIS_SPIN_LOCK *) (pLockOrg->pContent);
+	if (pLock != NULL) {
+		OS_INT_UNLOCK(pLock, IrqFlags);
+	} else
+		printk("lock> warning! the lock was freed!\n");
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get MAC address for the network interface.
+
+Arguments:
+	pDev			- the device
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+unsigned char *RtmpOsNetDevGetPhyAddr(VOID *pDev)
+{
+	return RTMP_OS_NETDEV_GET_PHYADDR((PNET_DEV) pDev);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Start network interface TX queue.
+
+Arguments:
+	pDev			- the device
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsNetQueueStart(PNET_DEV pDev)
+{
+	RTMP_OS_NETDEV_START_QUEUE(pDev);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Stop network interface TX queue.
+
+Arguments:
+	pDev			- the device
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsNetQueueStop(PNET_DEV pDev)
+{
+	RTMP_OS_NETDEV_STOP_QUEUE(pDev);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Wake up network interface TX queue.
+
+Arguments:
+	pDev			- the device
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsNetQueueWake(PNET_DEV pDev)
+{
+	RTMP_OS_NETDEV_WAKE_QUEUE(pDev);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Assign network interface to the packet.
+
+Arguments:
+	pPkt			- the packet
+	pDev			- the device
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsSetPktNetDev(VOID *pPkt, VOID *pDev)
+{
+	SET_OS_PKT_NETDEV(pPkt, (PNET_DEV) pDev);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Assign network interface type.
+
+Arguments:
+	pDev			- the device
+	Type			- the type
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsSetNetDevType(VOID *pDev, USHORT Type)
+{
+	RTMP_OS_NETDEV_SET_TYPE((PNET_DEV) pDev, Type);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Assign network interface type for monitor mode.
+
+Arguments:
+	pDev			- the device
+	Type			- the type
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsSetNetDevTypeMonitor(VOID *pDev)
+{
+	RTMP_OS_NETDEV_SET_TYPE((PNET_DEV) pDev, ARPHRD_IEEE80211_PRISM);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get PID.
+
+Arguments:
+	pPkt			- the packet
+	pDev			- the device
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsGetPid(IN ULONG *pDst,
+		  IN ULONG PID)
+{
+	RT_GET_OS_PID(*pDst, PID);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Wait for a moment.
+
+Arguments:
+	Time			- micro second
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsWait(UINT32 Time)
+{
+	OS_WAIT(Time);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Check if b is smaller than a.
+
+Arguments:
+	Time			- micro second
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+UINT32 RtmpOsTimerAfter(ULONG a, ULONG b)
+{
+	return RTMP_TIME_AFTER(a, b);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Check if b is not smaller than a.
+
+Arguments:
+	Time			- micro second
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+UINT32 RtmpOsTimerBefore(ULONG a, ULONG b)
+{
+	return RTMP_TIME_BEFORE(a, b);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get current system time.
+
+Arguments:
+	pTime			- system time (tick)
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsGetSystemUpTime(ULONG *pTime)
+{
+	NdisGetSystemUpTime(pTime);
+}
+
+/*
+========================================================================
+Routine Description:
+	Get OS tick unit.
+
+Arguments:
+	pOps			- Utility table
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+UINT32 RtmpOsTickUnitGet(VOID)
+{
+	return HZ;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	ntohs
+
+Arguments:
+	Value			- the value
+
+Return Value:
+	the value
+
+Note:
+========================================================================
+*/
+UINT16 RtmpOsNtohs(UINT16 Value)
+{
+	return OS_NTOHS(Value);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	htons
+
+Arguments:
+	Value			- the value
+
+Return Value:
+	the value
+
+Note:
+========================================================================
+*/
+UINT16 RtmpOsHtons(UINT16 Value)
+{
+	return OS_HTONS(Value);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	ntohl
+
+Arguments:
+	Value			- the value
+
+Return Value:
+	the value
+
+Note:
+========================================================================
+*/
+UINT32 RtmpOsNtohl(UINT32 Value)
+{
+	return OS_NTOHL(Value);
+}
+
+/*
+========================================================================
+Routine Description:
+	htonl
+
+Arguments:
+	Value			- the value
+
+Return Value:
+	the value
+
+Note:
+========================================================================
+*/
+UINT32 RtmpOsHtonl(UINT32 Value)
+{
+	return OS_HTONL(Value);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	get_unaligned for 16-bit value.
+
+Arguments:
+	pWord			- the value
+
+Return Value:
+	the value
+
+Note:
+========================================================================
+*/
+UINT16 RtmpOsGetUnaligned(UINT16 *pWord)
+{
+	return get_unaligned(pWord);
+}
+
+/*
+========================================================================
+Routine Description:
+	get_unaligned for 32-bit value.
+
+Arguments:
+	pWord			- the value
+
+Return Value:
+	the value
+
+Note:
+========================================================================
+*/
+UINT32 RtmpOsGetUnaligned32(UINT32 *pWord)
+{
+	return get_unaligned(pWord);
+}
+
+/*
+========================================================================
+Routine Description:
+	get_unaligned for long-bit value.
+
+Arguments:
+	pWord			- the value
+
+Return Value:
+	the value
+
+Note:
+========================================================================
+*/
+ULONG RtmpOsGetUnalignedlong(ULONG *pWord)
+{
+	return get_unaligned(pWord);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Get maximum scan data length.
+
+Arguments:
+	None
+
+Return Value:
+	length
+
+Note:
+	Used in site servey.
+========================================================================
+*/
+ULONG RtmpOsMaxScanDataGet(VOID)
+{
+	return IW_SCAN_MAX_DATA;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	copy_from_user
+
+Arguments:
+	to				-
+	from			-
+	n				- size
+
+Return Value:
+	copy size
+
+Note:
+========================================================================
+*/
+ULONG RtmpOsCopyFromUser(VOID *to, const void *from, ULONG n)
+{
+	return (copy_from_user(to, from, n));
+}
+
+
+/*
+========================================================================
+Routine Description:
+	copy_to_user
+
+Arguments:
+	to				-
+	from			-
+	n				- size
+
+Return Value:
+	copy size
+
+Note:
+========================================================================
+*/
+ULONG RtmpOsCopyToUser(VOID *to, const void *from, ULONG n)
+{
+	return (copy_to_user(to, from, n));
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize a semaphore.
+
+Arguments:
+	pSem			- the semaphore
+
+Return Value:
+	TRUE			- Successfully
+	FALSE			- Fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsSemaInitLocked(RTMP_OS_SEM *pSem, LIST_HEADER *pSemList)
+{
+	if (RTMP_OS_Alloc_RscOnly(pSem, sizeof (OS_SEM)) == FALSE) {
+		DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc semaphore fail!\n", __FUNCTION__));
+		return FALSE;
+	}
+
+	OS_SEM_EVENT_INIT_LOCKED((OS_SEM *) (pSem->pContent));
+	return TRUE;
+}
+
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize a semaphore.
+
+Arguments:
+	pSemOrg			- the semaphore
+
+Return Value:
+	TRUE			- Successfully
+	FALSE			- Fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsSemaInit(RTMP_OS_SEM *pSem, LIST_HEADER *pSemList)
+{
+	if (RTMP_OS_Alloc_RscOnly(pSem, sizeof (OS_SEM)) == FALSE) {
+		DBGPRINT(RT_DEBUG_ERROR,
+			 ("%s: alloc semaphore fail!\n", __FUNCTION__));
+		return FALSE;
+	}
+
+	OS_SEM_EVENT_INIT((OS_SEM *) (pSem->pContent));
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Destroy a semaphore.
+
+Arguments:
+	pSemOrg			- the semaphore
+
+Return Value:
+	TRUE			- Successfully
+	FALSE			- Fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsSemaDestory(RTMP_OS_SEM *pSemOrg)
+{
+	OS_SEM *pSem;
+
+	pSem = (OS_SEM *) (pSemOrg->pContent);
+	if (pSem != NULL) {
+		OS_SEM_EVENT_DESTORY(pSem);
+
+		os_free_mem(NULL, pSem);
+		pSemOrg->pContent = NULL;
+	} else
+		printk("sem> warning! double-free sem!\n");
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Wait a semaphore.
+
+Arguments:
+	pSemOrg			- the semaphore
+
+Return Value:
+	0				- Successfully
+	Otherwise		- Fail
+
+Note:
+========================================================================
+*/
+INT32 RtmpOsSemaWaitInterruptible(RTMP_OS_SEM *pSemOrg)
+{
+	OS_SEM *pSem;
+	INT Status = -1;
+
+	pSem = (OS_SEM *) (pSemOrg->pContent);
+	if (pSem != NULL)
+		OS_SEM_EVENT_WAIT(pSem, Status);
+	return Status;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Wake up a semaphore.
+
+Arguments:
+	pSemOrg			- the semaphore
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsSemaWakeUp(RTMP_OS_SEM *pSemOrg)
+{
+	OS_SEM *pSem;
+
+	pSem = (OS_SEM *) (pSemOrg->pContent);
+	if (pSem != NULL)
+		OS_SEM_EVENT_UP(pSem);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Check if we are in a interrupt.
+
+Arguments:
+	None
+
+Return Value:
+	0				- No
+	Otherwise		- Yes
+
+Note:
+========================================================================
+*/
+INT32 RtmpOsIsInInterrupt(VOID)
+{
+	return (in_interrupt());
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Copy the data buffer to the packet frame body.
+
+Arguments:
+	pAd				- WLAN control block pointer
+	pNetPkt			- the packet
+	ThisFrameLen	- copy length
+	pData			- the data buffer
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktBodyCopy(
+	PNET_DEV pNetDev,
+	PNDIS_PACKET pNetPkt,
+	ULONG ThisFrameLen,
+	PUCHAR pData)
+{
+	memcpy(skb_put(pNetPkt, ThisFrameLen), pData, ThisFrameLen);
+	SET_OS_PKT_NETDEV(pNetPkt, pNetDev);
+	RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pNetPkt), PKTSRC_NDIS);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Check if the packet is cloned.
+
+Arguments:
+	pNetPkt			- the packet
+
+Return Value:
+	TRUE			- Yes
+	Otherwise		- No
+
+Note:
+========================================================================
+*/
+INT RtmpOsIsPktCloned(PNDIS_PACKET pNetPkt)
+{
+	return OS_PKT_CLONED(pNetPkt);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Duplicate a packet.
+
+Arguments:
+	pNetPkt			- the packet
+
+Return Value:
+	the new packet
+
+Note:
+========================================================================
+*/
+PNDIS_PACKET RtmpOsPktCopy(PNDIS_PACKET pNetPkt)
+{
+	return skb_copy(RTPKT_TO_OSPKT(pNetPkt), GFP_ATOMIC);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Clone a packet.
+
+Arguments:
+	pNetPkt			- the packet
+
+Return Value:
+	the cloned packet
+
+Note:
+========================================================================
+*/
+PNDIS_PACKET RtmpOsPktClone(PNDIS_PACKET pNetPkt)
+{
+	return skb_clone(RTPKT_TO_OSPKT(pNetPkt), MEM_ALLOC_FLAG);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Assign the data pointer for the packet.
+
+Arguments:
+	pNetPkt			- the packet
+	*pData			- the data buffer
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktDataPtrAssign(PNDIS_PACKET pNetPkt, UCHAR *pData)
+{
+	SET_OS_PKT_DATAPTR(pNetPkt, pData);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Assign the data length for the packet.
+
+Arguments:
+	pNetPkt			- the packet
+	Len				- the data length
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktLenAssign(PNDIS_PACKET pNetPkt, LONG Len)
+{
+	SET_OS_PKT_LEN(pNetPkt, Len);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Adjust the tail pointer for the packet.
+
+Arguments:
+	pNetPkt			- the packet
+	removedTagLen	- the size for adjustment
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktTailAdjust(PNDIS_PACKET pNetPkt, UINT removedTagLen)
+{
+	OS_PKT_TAIL_ADJUST(pNetPkt, removedTagLen);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Adjust the data pointer for the packet.
+
+Arguments:
+	pNetPkt			- the packet
+	Len				- the size for adjustment
+
+Return Value:
+	the new data pointer for the packet
+
+Note:
+========================================================================
+*/
+PUCHAR RtmpOsPktTailBufExtend(PNDIS_PACKET pNetPkt, UINT Len)
+{
+	return OS_PKT_TAIL_BUF_EXTEND(pNetPkt, Len);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	adjust headroom for the packet.
+
+Arguments:
+	pNetPkt			- the packet
+	Len				- the size for adjustment
+
+Return Value:
+	the new data pointer for the packet
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktReserve(PNDIS_PACKET pNetPkt, UINT Len)
+{
+	OS_PKT_RESERVE(pNetPkt, Len);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Adjust the data pointer for the packet.
+
+Arguments:
+	pNetPkt			- the packet
+	Len				- the size for adjustment
+
+Return Value:
+	the new data pointer for the packet
+
+Note:
+========================================================================
+*/
+PUCHAR RtmpOsPktHeadBufExtend(PNDIS_PACKET pNetPkt, UINT Len)
+{
+	return OS_PKT_HEAD_BUF_EXTEND(pNetPkt, Len);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	
+
+Arguments:
+	pPkt			- the packet
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsPktInfPpaSend(PNDIS_PACKET pNetPkt)
+{
+#ifdef INF_PPA_SUPPORT
+	struct sk_buff *pRxPkt = RTPKT_TO_OSPKT(pNetPkt);
+	int ret = 0;
+	unsigned int ppa_flags = 0;	/* reserved for now */
+
+	pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
+
+	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);
+#endif /* INF_PPA_SUPPORT */
+}
+
+
+INT32 RtmpThreadPidKill(RTMP_OS_PID PID)
+{
+	return KILL_THREAD_PID(PID, SIGTERM, 1);
+}
+
+
+long RtmpOsSimpleStrtol(const char *cp, char **endp, unsigned int base)
+{
+	return simple_strtol(cp, endp, base);
+}
+
+
+BOOLEAN RtmpOsPktOffsetInit(VOID)
+{
+	struct sk_buff *pPkt = NULL;
+
+	if ((RTPktOffsetData == 0) && (RTPktOffsetLen == 0)
+	    && (RTPktOffsetCB == 0)) {
+		pPkt = kmalloc(sizeof (struct sk_buff), GFP_ATOMIC);
+		if (pPkt == NULL)
+			return FALSE;
+
+		RTPktOffsetData = (ULONG) (&(pPkt->data)) - (ULONG) pPkt;
+		RTPktOffsetLen = (ULONG) (&(pPkt->len)) - (ULONG) pPkt;
+		RTPktOffsetCB = (ULONG) (pPkt->cb) - (ULONG) pPkt;
+		kfree(pPkt);
+
+		DBGPRINT(RT_DEBUG_TRACE,
+			 ("packet> data offset = %lu\n", RTPktOffsetData));
+		DBGPRINT(RT_DEBUG_TRACE,
+			 ("packet> len offset = %lu\n", RTPktOffsetLen));
+		DBGPRINT(RT_DEBUG_TRACE,
+			 ("packet> cb offset = %lu\n", RTPktOffsetCB));
+	}
+
+	return TRUE;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize the OS atomic_t.
+
+Arguments:
+	pAtomic			- the atomic
+
+Return Value:
+	TRUE			- allocation successfully
+	FALSE			- allocation fail
+
+Note:
+========================================================================
+*/
+BOOLEAN RtmpOsAtomicInit(RTMP_OS_ATOMIC *pAtomic, LIST_HEADER *pAtomicList)
+{
+	if (RTMP_OS_Alloc_RscOnly(pAtomic, sizeof (atomic_t)) == FALSE) {
+		DBGPRINT(RT_DEBUG_ERROR, ("%s: alloc atomic fail!\n", __FUNCTION__));
+		return FALSE;	/* allocate fail */
+	}
+
+	return TRUE;
+}
+
+/*
+========================================================================
+Routine Description:
+	Initialize the OS atomic_t.
+
+Arguments:
+	pAtomic			- the atomic
+
+Return Value:
+	TRUE			- allocation successfully
+	FALSE			- allocation fail
+
+Note:
+========================================================================
+*/
+VOID RtmpOsAtomicDestroy(RTMP_OS_ATOMIC *pAtomic)
+{
+	if (pAtomic->pContent) {
+		os_free_mem(NULL, pAtomic->pContent);
+		pAtomic->pContent = NULL;
+	}
+}
+
+/*
+========================================================================
+Routine Description:
+	Atomic read a variable.
+
+Arguments:
+	pAtomic			- the atomic
+
+Return Value:
+	content
+
+Note:
+========================================================================
+*/
+LONG RtmpOsAtomicRead(RTMP_OS_ATOMIC *pAtomicSrc)
+{
+	if (pAtomicSrc->pContent)
+		return atomic_read((atomic_t *) (pAtomicSrc->pContent));
+	else
+		return 0;
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Atomic dec a variable.
+
+Arguments:
+	pAtomic			- the atomic
+
+Return Value:
+	content
+
+Note:
+========================================================================
+*/
+VOID RtmpOsAtomicDec(RTMP_OS_ATOMIC *pAtomicSrc)
+{
+	if (pAtomicSrc->pContent)
+		atomic_dec((atomic_t *) (pAtomicSrc->pContent));
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Sets a 32-bit variable to the specified value as an atomic operation.
+
+Arguments:
+	pAtomic			- the atomic
+	Value			- the value to be exchanged
+
+Return Value:
+	the initial value of the pAtomicSrc parameter
+
+Note:
+========================================================================
+*/
+VOID RtmpOsAtomicInterlockedExchange(
+	RTMP_OS_ATOMIC *pAtomicSrc,
+	LONG Value)
+{
+	if (pAtomicSrc->pContent)
+		InterlockedExchange((atomic_t *) (pAtomicSrc->pContent), Value);
+}
+
+
+/*
+========================================================================
+Routine Description:
+	Initialize the OS utilities.
+
+Arguments:
+	pOps			- Utility table
+
+Return Value:
+	None
+
+Note:
+========================================================================
+*/
+VOID RtmpOsOpsInit(RTMP_OS_ABL_OPS *pOps)
+{
+	pOps->ra_printk = (RTMP_PRINTK)printk;
+	pOps->ra_snprintf = (RTMP_SNPRINTF)snprintf;
+}
+
+#else /* OS_ABL_FUNC_SUPPORT */
+
+
+void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfoOrg, BOOLEAN bSet)
+{
+	__RtmpOSFSInfoChange(pOSFSInfoOrg, bSet);
+}
+
+
+/* timeout -- ms */
+VOID RTMP_SetPeriodicTimer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout)
+{
+	__RTMP_SetPeriodicTimer(pTimerOrg, timeout);
+}
+
+
+/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
+VOID RTMP_OS_Init_Timer(
+	VOID *pReserved,
+	NDIS_MINIPORT_TIMER *pTimerOrg,
+	TIMER_FUNCTION function,
+	PVOID data,
+	LIST_HEADER *pTimerList)
+{
+	__RTMP_OS_Init_Timer(pReserved, pTimerOrg, function, data);
+}
+
+
+VOID RTMP_OS_Add_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout)
+{
+	__RTMP_OS_Add_Timer(pTimerOrg, timeout);
+}
+
+
+VOID RTMP_OS_Mod_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, unsigned long timeout)
+{
+	__RTMP_OS_Mod_Timer(pTimerOrg, timeout);
+}
+
+
+VOID RTMP_OS_Del_Timer(NDIS_MINIPORT_TIMER *pTimerOrg, BOOLEAN *pCancelled)
+{
+	__RTMP_OS_Del_Timer(pTimerOrg, pCancelled);
+}
+
+
+VOID RTMP_OS_Release_Timer(NDIS_MINIPORT_TIMER *pTimerOrg)
+{
+	__RTMP_OS_Release_Timer(pTimerOrg);
+}
+
+
+NDIS_STATUS RtmpOSTaskKill(RTMP_OS_TASK *pTask)
+{
+	return __RtmpOSTaskKill(pTask);
+}
+
+
+INT RtmpOSTaskNotifyToExit(RTMP_OS_TASK *pTask)
+{
+	return __RtmpOSTaskNotifyToExit(pTask);
+}
+
+
+void RtmpOSTaskCustomize(RTMP_OS_TASK *pTask)
+{
+	__RtmpOSTaskCustomize(pTask);
+}
+
+
+NDIS_STATUS RtmpOSTaskAttach(
+	RTMP_OS_TASK *pTask,
+	RTMP_OS_TASK_CALLBACK fn,
+	ULONG arg)
+{
+	return __RtmpOSTaskAttach(pTask, fn, arg);
+}
+
+
+NDIS_STATUS RtmpOSTaskInit(
+	RTMP_OS_TASK *pTask,
+	PSTRING pTaskName,
+	VOID *pPriv,
+	LIST_HEADER *pTaskList,
+	LIST_HEADER *pSemList)
+{
+	return __RtmpOSTaskInit(pTask, pTaskName, pPriv, pSemList);
+}
+
+
+BOOLEAN RtmpOSTaskWait(VOID *pReserved, RTMP_OS_TASK * pTask, INT32 *pStatus)
+{
+	return __RtmpOSTaskWait(pReserved, pTask, pStatus);
+}
+
+
+VOID RtmpOsTaskWakeUp(RTMP_OS_TASK *pTask)
+{
+#ifdef KTHREAD_SUPPORT
+	WAKE_UP(pTask);
+#else
+	RTMP_SEM_EVENT_UP(&pTask->taskSema);
+#endif
+}
+
+#endif /* OS_ABL_FUNC_SUPPORT */
+
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* Re: Patch
  2013-11-22 17:36 ` Patch Levente Kurusa
@ 2013-11-25  8:58     ` Daniel Vetter
  0 siblings, 0 replies; 80+ messages in thread
From: Daniel Vetter @ 2013-11-25  8:58 UTC (permalink / raw)
  To: Levente Kurusa
  Cc: Arthur Schwalbenberg, Daniel Vetter, David Airlie, intel-gfx,
	dri-devel, linux-kernel, Arthur Schwalbenberg

On Fri, Nov 22, 2013 at 06:36:48PM +0100, Levente Kurusa wrote:
> 2013-11-22 17:35, Arthur Schwalbenberg:
> > 
> > From 340fa01dfe8f699e27ece111996ea088bca6b5c4 Mon Sep 17 00:00:00 2001
> > From: Arthur Schwalbenberg <aschwal@hotmail.com>
> > Date: Thu, 21 Nov 2013 19:42:44 -0500
> > Subject: [PATCH] Staging: Fixed compilar warnings and coding style
> > issues in i915_debugfs.c
> > MIME-Version: 1.0
> > Content-Type: text/plain; charset=UTF-8
> > Content-Transfer-Encoding: 8bit
> > 
> > This is a patch fixing both a compilar warning:
> > ‘val’ may be used uninitialized in this function
> > and various coding style issues which include line length
> > warnings and a few errors as defined by 'checkpatch.pl' tool
> > 
> > Signed-off-by: Arthur Schwalbenberg <aschwal@hotmail.com>
> 
> Hi,
> 
> When you break 80+ lines into two lines, you should also
> indent the newly created line so that it shows that it is a part of something.
> I as well don't think it is worth splitting lines that are 84 characters long into
> two lines, that just doesn't make sense.
> 
> Also, your patch seems (atleast to me) a 'bit' whitespace damaged.

Also, please don't smash different changes into the same patch. Especially
pure whitespace changes _must_ be separate from actual code changes.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Patch
@ 2013-11-25  8:58     ` Daniel Vetter
  0 siblings, 0 replies; 80+ messages in thread
From: Daniel Vetter @ 2013-11-25  8:58 UTC (permalink / raw)
  To: Levente Kurusa
  Cc: Daniel Vetter, intel-gfx, linux-kernel, dri-devel,
	Arthur Schwalbenberg, Arthur Schwalbenberg

On Fri, Nov 22, 2013 at 06:36:48PM +0100, Levente Kurusa wrote:
> 2013-11-22 17:35, Arthur Schwalbenberg:
> > 
> > From 340fa01dfe8f699e27ece111996ea088bca6b5c4 Mon Sep 17 00:00:00 2001
> > From: Arthur Schwalbenberg <aschwal@hotmail.com>
> > Date: Thu, 21 Nov 2013 19:42:44 -0500
> > Subject: [PATCH] Staging: Fixed compilar warnings and coding style
> > issues in i915_debugfs.c
> > MIME-Version: 1.0
> > Content-Type: text/plain; charset=UTF-8
> > Content-Transfer-Encoding: 8bit
> > 
> > This is a patch fixing both a compilar warning:
> > ‘val’ may be used uninitialized in this function
> > and various coding style issues which include line length
> > warnings and a few errors as defined by 'checkpatch.pl' tool
> > 
> > Signed-off-by: Arthur Schwalbenberg <aschwal@hotmail.com>
> 
> Hi,
> 
> When you break 80+ lines into two lines, you should also
> indent the newly created line so that it shows that it is a part of something.
> I as well don't think it is worth splitting lines that are 84 characters long into
> two lines, that just doesn't make sense.
> 
> Also, your patch seems (atleast to me) a 'bit' whitespace damaged.

Also, please don't smash different changes into the same patch. Especially
pure whitespace changes _must_ be separate from actual code changes.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Patch
  2013-11-22 16:35 Patch Arthur Schwalbenberg
@ 2013-11-22 17:36 ` Levente Kurusa
  2013-11-25  8:58     ` Patch Daniel Vetter
  0 siblings, 1 reply; 80+ messages in thread
From: Levente Kurusa @ 2013-11-22 17:36 UTC (permalink / raw)
  To: Arthur Schwalbenberg, Daniel Vetter, David Airlie, intel-gfx,
	dri-devel, linux-kernel, Arthur Schwalbenberg

2013-11-22 17:35, Arthur Schwalbenberg:
> 
> From 340fa01dfe8f699e27ece111996ea088bca6b5c4 Mon Sep 17 00:00:00 2001
> From: Arthur Schwalbenberg <aschwal@hotmail.com>
> Date: Thu, 21 Nov 2013 19:42:44 -0500
> Subject: [PATCH] Staging: Fixed compilar warnings and coding style
> issues in i915_debugfs.c
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
> 
> This is a patch fixing both a compilar warning:
> ‘val’ may be used uninitialized in this function
> and various coding style issues which include line length
> warnings and a few errors as defined by 'checkpatch.pl' tool
> 
> Signed-off-by: Arthur Schwalbenberg <aschwal@hotmail.com>

Hi,

When you break 80+ lines into two lines, you should also
indent the newly created line so that it shows that it is a part of something.
I as well don't think it is worth splitting lines that are 84 characters long into
two lines, that just doesn't make sense.

Also, your patch seems (atleast to me) a 'bit' whitespace damaged.

-- 
Regards,
Levente Kurusa

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
@ 2013-11-22 16:35 Arthur Schwalbenberg
  2013-11-22 17:36 ` Patch Levente Kurusa
  0 siblings, 1 reply; 80+ messages in thread
From: Arthur Schwalbenberg @ 2013-11-22 16:35 UTC (permalink / raw)
  To: Daniel Vetter, David Airlie, intel-gfx, dri-devel, linux-kernel,
	Arthur Schwalbenberg


 From 340fa01dfe8f699e27ece111996ea088bca6b5c4 Mon Sep 17 00:00:00 2001
From: Arthur Schwalbenberg <aschwal@hotmail.com>
Date: Thu, 21 Nov 2013 19:42:44 -0500
Subject: [PATCH] Staging: Fixed compilar warnings and coding style
issues in i915_debugfs.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This is a patch fixing both a compilar warning:
‘val’ may be used uninitialized in this function
and various coding style issues which include line length
warnings and a few errors as defined by 'checkpatch.pl' tool

Signed-off-by: Arthur Schwalbenberg <aschwal@hotmail.com>
---
drivers/gpu/drm/i915/i915_debugfs.c | 75 ++++++++++++++++++++---------------
1 file changed, 44 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 6ed45a9..01135d4 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2008 Intel Corporation
+ * Copyright © 2008 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -87,8 +87,8 @@ static int i915_capabilities(struct seq_file *m, void 
*data)

seq_printf(m, "gen: %d\n", info->gen);
seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
-#define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
-#define SEP_SEMICOLON ;
+#define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x));
+#define SEP_SEMICOLON
DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
#undef PRINT_FLAG
#undef SEP_SEMICOLON
@@ -144,7 +144,7 @@ describe_obj(struct seq_file *m, struct 
drm_i915_gem_object *obj)
if (obj->pin_count)
seq_printf(m, " (pinned x %d)", obj->pin_count);
if (obj->pin_display)
- seq_printf(m, " (display)");
+ seq_puts(m, " (display)");
if (obj->fence_reg != I915_FENCE_REG_NONE)
seq_printf(m, " (fence: %d)", obj->fence_reg);
list_for_each_entry(vma, &obj->vma_list, vma_link) {
@@ -210,9 +210,9 @@ static int i915_gem_object_list_info(struct seq_file 
*m, void *data)

total_obj_size = total_gtt_size = count = 0;
list_for_each_entry(vma, head, mm_list) {
- seq_printf(m, " ");
+ seq_puts(m, " ");
describe_obj(m, vma->obj);
- seq_printf(m, "\n");
+ seq_puts(m, "\n");
total_obj_size += vma->obj->base.size;
total_gtt_size += vma->node.size;
count++;
@@ -333,7 +333,7 @@ static int per_file_stats(int id, void *ptr, void *data)
} \
} while (0)

-static int i915_gem_object_info(struct seq_file *m, void* data)
+static int i915_gem_object_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;
@@ -460,6 +460,7 @@ static int i915_gem_gtt_info(struct seq_file *m, 
void *data)

static int i915_gem_pageflip_info(struct seq_file *m, void *data)
{
+ struct drm_i915_gem_object *obj = NULL;
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
unsigned long flags;
@@ -487,19 +488,22 @@ static int i915_gem_pageflip_info(struct seq_file 
*m, void *data)
seq_puts(m, "Stall check enabled, ");
else
seq_puts(m, "Stall check waiting for page flip ioctl, ");
- seq_printf(m, "%d prepares\n", atomic_read(&work->pending));
+
+ seq_printf(m, "%d prepares\n",
+ atomic_read(&work->pending));

if (work->old_fb_obj) {
- struct drm_i915_gem_object *obj = work->old_fb_obj;
+ obj = work->old_fb_obj;
if (obj)
seq_printf(m, "Old framebuffer gtt_offset 0x%08lx\n",
- i915_gem_obj_ggtt_offset(obj));
+ i915_gem_obj_ggtt_offset(obj));
}
if (work->pending_flip_obj) {
- struct drm_i915_gem_object *obj = work->pending_flip_obj;
+ obj = work->pending_flip_obj;
if (obj)
- seq_printf(m, "New framebuffer gtt_offset 0x%08lx\n",
- i915_gem_obj_ggtt_offset(obj));
+ seq_printf(m,
+ "New framebuffer gtt_offset 0x%08lx\n",
+ i915_gem_obj_ggtt_offset(obj));
}
}
spin_unlock_irqrestore(&dev->event_lock, flags);
@@ -530,9 +534,8 @@ static int i915_gem_request_info(struct seq_file *m, 
void *data)
list_for_each_entry(gem_request,
&ring->request_list,
list) {
- seq_printf(m, " %d @ %d\n",
- gem_request->seqno,
- (int) (jiffies - gem_request->emitted_jiffies));
+ seq_printf(m, " %d @ %d\n", gem_request->seqno,
+ (int) (jiffies - gem_request->emitted_jiffies));
}
count++;
}
@@ -909,7 +912,9 @@ static int i915_rstdby_delays(struct seq_file *m, 
void *unused)

mutex_unlock(&dev->struct_mutex);

- seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, 
(crstanddelay & 0x3f));
+ seq_printf(m, "w/ctx: %d, w/o ctx: %d\n",
+ (crstanddelay >> 8) & 0x3f,
+ (crstanddelay & 0x3f));

return 0;
}
@@ -929,10 +934,11 @@ static int i915_cur_delayinfo(struct seq_file *m, 
void *unused)

seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf);
seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f);
- seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
- MEMSTAT_VID_SHIFT);
+ seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK)
+ >> MEMSTAT_VID_SHIFT);
seq_printf(m, "Current P-state: %d\n",
- (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
+ (rgvstat & MEMSTAT_PSTATE_MASK) >>
+ MEMSTAT_PSTATE_SHIFT);
} else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
@@ -1173,13 +1179,13 @@ static int gen6_drpc_info(struct seq_file *m)
spin_unlock_irq(&dev_priv->uncore.lock);

if (forcewake_count) {
- seq_puts(m, "RC information inaccurate because somebody "
- "holds a forcewake reference \n");
+ seq_puts(m, "RC information inaccurate because somebody holds a 
forcewake reference\n");
} else {
/* NB: we cannot use forcewake, else we read the wrong values */
while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1))
udelay(10);
- seq_printf(m, "RC information accurate: %s\n", yesno(count < 51));
+ seq_printf(m, "RC information accurate: %s\n",
+ yesno(count < 51));
}

gt_core_status = readl(dev_priv->regs + GEN6_GT_CORE_STATUS);
@@ -1549,7 +1555,8 @@ static int i915_context_status(struct seq_file *m, 
void *unused)
describe_ctx(m, ctx);
for_each_ring(ring, dev_priv, i)
if (ring->default_context == ctx)
- seq_printf(m, "(default context %s) ", ring->name);
+ seq_printf(m, "(default context %s) ",
+ ring->name);

describe_obj(m, ctx->obj);
seq_putc(m, '\n');
@@ -1683,10 +1690,15 @@ static void gen6_ppgtt_info(struct seq_file *m, 
struct drm_device *dev)
for_each_ring(ring, dev_priv, i) {
seq_printf(m, "%s\n", ring->name);
if (INTEL_INFO(dev)->gen == 7)
- seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(RING_MODE_GEN7(ring)));
- seq_printf(m, "PP_DIR_BASE: 0x%08x\n", I915_READ(RING_PP_DIR_BASE(ring)));
- seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n", 
I915_READ(RING_PP_DIR_BASE_READ(ring)));
- seq_printf(m, "PP_DIR_DCLV: 0x%08x\n", I915_READ(RING_PP_DIR_DCLV(ring)));
+ seq_printf(m, "GFX_MODE: 0x%08x\n",
+ I915_READ(RING_MODE_GEN7(ring)));
+
+ seq_printf(m, "PP_DIR_BASE: 0x%08x\n",
+ I915_READ(RING_PP_DIR_BASE(ring)));
+ seq_printf(m, "PP_DIR_BASE_READ: 0x%08x\n",
+ I915_READ(RING_PP_DIR_BASE_READ(ring)));
+ seq_printf(m, "PP_DIR_DCLV: 0x%08x\n",
+ I915_READ(RING_PP_DIR_DCLV(ring)));
}
if (dev_priv->mm.aliasing_ppgtt) {
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
@@ -2347,7 +2359,7 @@ static int pipe_crc_set_source(struct drm_device 
*dev, enum pipe pipe,
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
- u32 val;
+ u32 val = 0;
int ret;

if (pipe_crc->source == source)
@@ -2362,7 +2374,7 @@ static int pipe_crc_set_source(struct drm_device 
*dev, enum pipe pipe,
else if (INTEL_INFO(dev)->gen < 5)
ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val);
else if (IS_VALLEYVIEW(dev))
- ret = vlv_pipe_crc_ctl_reg(dev,pipe, &source, &val);
+ ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val);
else if (IS_GEN5(dev) || IS_GEN6(dev))
ret = ilk_pipe_crc_ctl_reg(&source, &val);
else
@@ -3046,7 +3058,8 @@ static const struct drm_info_list 
i915_debugfs_list[] = {
{"i915_gem_gtt", i915_gem_gtt_info, 0},
{"i915_gem_pinned", i915_gem_gtt_info, 0, (void *) PINNED_LIST},
{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
- {"i915_gem_inactive", i915_gem_object_list_info, 0, (void *) 
INACTIVE_LIST},
+ {"i915_gem_inactive", i915_gem_object_list_info, 0,
+ (void *) INACTIVE_LIST},
{"i915_gem_stolen", i915_gem_stolen_list_info },
{"i915_gem_pageflip", i915_gem_pageflip_info, 0},
{"i915_gem_request", i915_gem_request_info, 0},
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 80+ messages in thread

* patch
@ 2010-05-04 16:48 Kristoffer Ericson
  0 siblings, 0 replies; 80+ messages in thread
From: Kristoffer Ericson @ 2010-05-04 16:48 UTC (permalink / raw)
  To: jeff; +Cc: linux-kernel

Hey,

did you get my patch concerning those hash changes? Havent gotten any reply.

Best wishes
Kristoffer

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2009-01-29 10:11 gabriele.paoloni
  0 siblings, 0 replies; 80+ messages in thread
From: gabriele.paoloni @ 2009-01-29 10:11 UTC (permalink / raw)
  To: netdev, redesign, ppp_mp_explode
  Cc: gabriele.paoloni, ken.reynolds, arjan.van.de.ven

Hi,
 
My name is Gabriele Paoloni, I am a Software Engineer working in the Intel
Research and Development Center in Shannon, Ireland.
I found the PPP subsystem to not work properly when connecting channels
with different speeds to the same bundle.

Problem Description:

As the "ppp_mp_explode" function fragments the sk_buff buffer evenly among
 the PPP channels that are connected to a certain PPP unit to make up a bundle,
 if we are transmitting using an upper layer protocol that requires an Ack 
before sending the next packet (like TCP/IP for example), we will have a 
bandwidth bottleneck on the slowest channel of the bundle. 
Let's clarify by an example. Let's consider a scenario where we have two PPP 
links making up a bundle: a slow link (10KB/sec) and a fast link (1000KB/sec) 
working at the best (full bandwidth). On the top we have a TCP/IP stack sending 
a 1000 Bytes sk_buff buffer down to the PPP subsystem. The  "ppp_mp_explode" 
function will divide the buffer in two fragments of 500B each (we are neglecting 
all the headers, crc, flags etc?.). Before the TCP/IP stack sends out the next 
buffer, it will have to wait for the ACK response from the remote peer, so it will 
have to wait for both fragments to have been sent over the two PPP links, received 
by the remote peer and reconstructed. The resulting behaviour is that, rather than 
having a bundle working @1010KB/sec (the sum of the channels bandwidths), we'll 
have a bundle working @20KB/sec (the double of the slowest channels bandwidth).


Problem Solution:

The problem has been solved by redesigning the "ppp_mp_explode" function in such 
a way to make it split the sk_buff buffer according to the speeds of the underlying 
PPP channels (the speeds of the serial interfaces respectively attached to the PPP 
channels). Referring to the above example, the redesigned "ppp_mp_explode" function 
will now divide the 1000 Bytes buffer into two fragments whose sizes are set 
according to the speeds of the channels where they are going to be sent on (e.g . 
10 Byets on 10KB/sec channel and 990 Bytes on 1000KB/sec channel). 
The reworked function grants the same performances of the original one in optimal 
working conditions (i.e. a bundle made up of PPP links all working at the same 
speed), while greatly improving performances on the bundles made up of channels 
working at different speeds.


Find inline a possible solution patch.

 
Note: the kernel patch has been generated against the last stable version
      2.6.28.2
 
Best Regards
 
Gabriele Paoloni
 
email: gabriele.paoloni@intel.com
phone: +353 6 147 7753
mobile1: 00353 8333 52390
mobile2: 0039 3937498940
 
 
*******************************************************************************
*******************************************************************************
*******************************************************************************





Signed-off-by: Gabriele Paoloni <paoloni.gabriele@gmail.com> <gabriele.paoloni@intel.com>

diff -urN ./linux-2.6.28.2/drivers/net/ppp_async.c ./linux-2.6.28.2.new/drivers/net/ppp_async.c
--- ./linux-2.6.28.2/drivers/net/ppp_async.c	2009-01-25 00:42:07.000000000 +0000
+++ ./linux-2.6.28.2.new/drivers/net/ppp_async.c	2009-01-28 16:54:37.000000000 +0000
@@ -157,6 +157,7 @@
 {
 	struct asyncppp *ap;
 	int err;
+	int speed;
 
 	if (tty->ops->write == NULL)
 		return -EOPNOTSUPP;
@@ -187,6 +188,8 @@
 	ap->chan.private = ap;
 	ap->chan.ops = &async_ops;
 	ap->chan.mtu = PPP_MRU;
+	speed = tty_get_baud_rate(tty);
+	ap->chan.speed = speed;
 	err = ppp_register_channel(&ap->chan);
 	if (err)
 		goto out_free;
diff -urN ./linux-2.6.28.2/drivers/net/ppp_generic.c ./linux-2.6.28.2.new/drivers/net/ppp_generic.c
--- ./linux-2.6.28.2/drivers/net/ppp_generic.c	2009-01-25 00:42:07.000000000 +0000
+++ ./linux-2.6.28.2.new/drivers/net/ppp_generic.c	2009-01-28 16:53:06.000000000 +0000
@@ -160,6 +160,7 @@
 	u8		avail;		/* flag used in multilink stuff */
 	u8		had_frag;	/* >= 1 fragments have been sent */
 	u32		lastseq;	/* MP: last sequence # received */
+	int     speed;		/* speed of the corresponding ppp channel*/
 #endif /* CONFIG_PPP_MULTILINK */
 };
 
@@ -1235,138 +1236,181 @@
  */
 static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
 {
-	int len, fragsize;
-	int i, bits, hdrlen, mtu;
-	int flen;
-	int navail, nfree;
-	int nbigger;
+	int	len, totlen;
+	int	i, bits, hdrlen, mtu;
+	int	flen;
+	int	navail,	nfree, nzero;
+	int	nbigger;
+	int	totspeed;
+	int	totfree;
 	unsigned char *p, *q;
 	struct list_head *list;
 	struct channel *pch;
 	struct sk_buff *frag;
 	struct ppp_channel *chan;
 
-	nfree = 0;	/* # channels which have no packet already queued */
+	totspeed = 0; /*total bitrate of the bundle*/
+	nfree =	0;	/* # channels which	have no	packet already queued */
 	navail = 0;	/* total # of usable channels (not deregistered) */
+	nzero =	0; /* number of	channels with zero speed associated*/
+	totfree	= 0; /*total # of channels available and
+				  *having no queued packets before
+				  *starting the fragmentation*/
+
 	hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
-	i = 0;
-	list_for_each_entry(pch, &ppp->channels, clist) {
+	i =	0;
+	list_for_each_entry(pch, &ppp->channels, clist)	{
 		navail += pch->avail = (pch->chan != NULL);
-		if (pch->avail) {
+		pch->speed = pch->chan->speed;
+		if (pch->avail)	{
 			if (skb_queue_empty(&pch->file.xq) ||
-			    !pch->had_frag) {
-				pch->avail = 2;
-				++nfree;
-			}
-			if (!pch->had_frag && i < ppp->nxchan)
-				ppp->nxchan = i;
+				!pch->had_frag)	{
+					if (pch->speed == 0)
+						nzero++;
+					else
+						totspeed += pch->speed;
+
+					pch->avail = 2;
+					++nfree;
+					++totfree;
+				}
+			if (!pch->had_frag && i	< ppp->nxchan)
+				ppp->nxchan	= i;
 		}
 		++i;
 	}
-
 	/*
-	 * Don't start sending this packet unless at least half of
-	 * the channels are free.  This gives much better TCP
-	 * performance if we have a lot of channels.
+	 * Don't start sending this	packet unless at least half	of
+	 * the channels	are	free.  This	gives much better TCP
+	 * performance if we have a	lot	of channels.
 	 */
-	if (nfree == 0 || nfree < navail / 2)
-		return 0;	/* can't take now, leave it in xmit_pending */
+	if (nfree == 0 || nfree	< navail / 2)
+		return 0; /* can't take now, leave it in xmit_pending	*/
 
 	/* Do protocol field compression (XXX this should be optional) */
-	p = skb->data;
-	len = skb->len;
+	p =	skb->data;
+	len	= skb->len;
 	if (*p == 0) {
 		++p;
 		--len;
 	}
 
-	/*
-	 * Decide on fragment size.
-	 * We create a fragment for each free channel regardless of
-	 * how small they are (i.e. even 0 length) in order to minimize
-	 * the time that it will take to detect when a channel drops
-	 * a fragment.
-	 */
-	fragsize = len;
-	if (nfree > 1)
-		fragsize = DIV_ROUND_UP(fragsize, nfree);
-	/* nbigger channels get fragsize bytes, the rest get fragsize-1,
-	   except if nbigger==0, then they all get fragsize. */
-	nbigger = len % nfree;
+	totlen = len;
+	nbigger	= len %	nfree;
 
-	/* skip to the channel after the one we last used
-	   and start at that one */
+	/* skip	to the channel after the one we	last used
+	   and start at	that one */
 	list = &ppp->channels;
-	for (i = 0; i < ppp->nxchan; ++i) {
+	for	(i = 0;	i <	ppp->nxchan; ++i) {
 		list = list->next;
-		if (list == &ppp->channels) {
-			i = 0;
+		if (list ==	&ppp->channels)	{
+			i =	0;
 			break;
 		}
 	}
 
-	/* create a fragment for each channel */
+	/* create a	fragment for each channel */
 	bits = B;
-	while (nfree > 0 || len > 0) {
+	while (nfree > 0 &&	len	> 0) {
 		list = list->next;
-		if (list == &ppp->channels) {
-			i = 0;
+		if (list ==	&ppp->channels)	{
+			i =	0;
 			continue;
 		}
-		pch = list_entry(list, struct channel, clist);
+		pch	= list_entry(list, struct channel, clist);
 		++i;
 		if (!pch->avail)
 			continue;
 
 		/*
-		 * Skip this channel if it has a fragment pending already and
-		 * we haven't given a fragment to all of the free channels.
+		 * Skip	this channel if	it has a fragment pending already and
+		 * we haven't given	a fragment to all of the free channels.
 		 */
 		if (pch->avail == 1) {
-			if (nfree > 0)
+			if (nfree >	0)
 				continue;
 		} else {
-			--nfree;
 			pch->avail = 1;
 		}
 
 		/* check the channel's mtu and whether it is still attached. */
 		spin_lock_bh(&pch->downl);
 		if (pch->chan == NULL) {
-			/* can't use this channel, it's being deregistered */
+			/* can't use this channel, it's	being deregistered */
+			if (pch->speed == 0)
+				nzero--;
+			else
+				totspeed -=	pch->speed;
+
 			spin_unlock_bh(&pch->downl);
 			pch->avail = 0;
-			if (--navail == 0)
+			totlen = len;
+			totfree--;
+			nfree--;
+			if (--navail ==	0)
 				break;
 			continue;
 		}
 
 		/*
-		 * Create a fragment for this channel of
-		 * min(max(mtu+2-hdrlen, 4), fragsize, len) bytes.
-		 * If mtu+2-hdrlen < 4, that is a ridiculously small
-		 * MTU, so we use mtu = 2 + hdrlen.
+		*if the channel speed is not set divide
+		*the packet	evenly among the free channels;
+		*otherwise divide it according to the speed
+		*of the channel we are going to transmit on
+		*/
+		if (pch->speed == 0) {
+			flen = totlen/nfree	;
+			if (nbigger > 0) {
+				flen++;
+				nbigger--;
+			}
+		} else {
+			flen = (((totfree - nzero)*(totlen + hdrlen*totfree)) /
+				((totspeed*totfree)/pch->speed)) - hdrlen;
+			if (nbigger > 0) {
+				flen += ((totfree - nzero)*pch->speed)/totspeed;
+				nbigger -= ((totfree - nzero)*pch->speed)/
+							totspeed;
+			}
+		}
+		nfree--;
+
+		/*
+		 *check	if we are on the last channel or
+		 *we exceded the lenght	of the data	to
+		 *fragment
+		 */
+		if ((nfree == 0) || (flen > len))
+			flen = len;
+		/*
+		 *it is not worth to tx on slow channels:
+		 *in that case from the resulting flen according to the
+		 *above formula will be equal or less than zero.
+		 *Skip the channel in this case
 		 */
-		if (fragsize > len)
-			fragsize = len;
-		flen = fragsize;
-		mtu = pch->chan->mtu + 2 - hdrlen;
-		if (mtu < 4)
-			mtu = 4;
+		if (flen <=	0) {
+			pch->avail = 2;
+			spin_unlock_bh(&pch->downl);
+			continue;
+		}
+
+		mtu	= pch->chan->mtu + 2 - hdrlen;
+		if (mtu	< 4)
+			mtu	= 4;
 		if (flen > mtu)
 			flen = mtu;
-		if (flen == len && nfree == 0)
-			bits |= E;
-		frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
+		if (flen ==	len)
+			bits |=	E;
+		frag = alloc_skb(flen +	hdrlen + (flen == 0), GFP_ATOMIC);
 		if (!frag)
 			goto noskb;
-		q = skb_put(frag, flen + hdrlen);
+		q =	skb_put(frag, flen + hdrlen);
 
-		/* make the MP header */
+		/* make	the	MP header */
 		q[0] = PPP_MP >> 8;
 		q[1] = PPP_MP;
 		if (ppp->flags & SC_MP_XSHORTSEQ) {
-			q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
+			q[2] = bits	+ ((ppp->nxseq >> 8) & 0xf);
 			q[3] = ppp->nxseq;
 		} else {
 			q[2] = bits;
@@ -1375,43 +1419,28 @@
 			q[5] = ppp->nxseq;
 		}
 
-		/*
-		 * Copy the data in.
-		 * Unfortunately there is a bug in older versions of
-		 * the Linux PPP multilink reconstruction code where it
-		 * drops 0-length fragments.  Therefore we make sure the
-		 * fragment has at least one byte of data.  Any bytes
-		 * we add in this situation will end up as padding on the
-		 * end of the reconstructed packet.
-		 */
-		if (flen == 0)
-			*skb_put(frag, 1) = 0;
-		else
-			memcpy(q + hdrlen, p, flen);
+		memcpy(q + hdrlen, p, flen);
 
 		/* try to send it down the channel */
 		chan = pch->chan;
-		if (!skb_queue_empty(&pch->file.xq) ||
-		    !chan->ops->start_xmit(chan, frag))
+		if (!skb_queue_empty(&pch->file.xq)	||
+			!chan->ops->start_xmit(chan, frag))
 			skb_queue_tail(&pch->file.xq, frag);
-		pch->had_frag = 1;
+		pch->had_frag =	1;
 		p += flen;
-		len -= flen;
+		len	-= flen;
 		++ppp->nxseq;
 		bits = 0;
 		spin_unlock_bh(&pch->downl);
-
-		if (--nbigger == 0 && fragsize > 0)
-			--fragsize;
 	}
-	ppp->nxchan = i;
+	ppp->nxchan	= i;
 
 	return 1;
 
  noskb:
 	spin_unlock_bh(&pch->downl);
 	if (ppp->debug & 1)
-		printk(KERN_ERR "PPP: no memory (fragment)\n");
+		printk(KERN_ERR	"PPP: no memory	(fragment)\n");
 	++ppp->dev->stats.tx_errors;
 	++ppp->nxseq;
 	return 1;	/* abandon the frame */
diff -urN ./linux-2.6.28.2/drivers/net/ppp_synctty.c ./linux-2.6.28.2.new/drivers/net/ppp_synctty.c
--- ./linux-2.6.28.2/drivers/net/ppp_synctty.c	2009-01-25 00:42:07.000000000 +0000
+++ ./linux-2.6.28.2.new/drivers/net/ppp_synctty.c	2009-01-28 16:55:16.000000000 +0000
@@ -206,6 +206,7 @@
 {
 	struct syncppp *ap;
 	int err;
+	int speed;
 
 	if (tty->ops->write == NULL)
 		return -EOPNOTSUPP;
@@ -234,6 +235,8 @@
 	ap->chan.ops = &sync_ops;
 	ap->chan.mtu = PPP_MRU;
 	ap->chan.hdrlen = 2;	/* for A/C bytes */
+	speed = tty_get_baud_rate(tty);
+	ap->chan.speed = speed;
 	err = ppp_register_channel(&ap->chan);
 	if (err)
 		goto out_free;
diff -urN ./linux-2.6.28.2/include/linux/ppp_channel.h ./linux-2.6.28.2.new/include/linux/ppp_channel.h
--- ./linux-2.6.28.2/include/linux/ppp_channel.h	2009-01-25 00:42:07.000000000 +0000
+++ ./linux-2.6.28.2.new/include/linux/ppp_channel.h	2009-01-28 16:54:01.000000000 +0000
@@ -39,8 +39,8 @@
 	int		mtu;		/* max transmit packet size */
 	int		hdrlen;		/* amount of headroom channel needs */
 	void		*ppp;		/* opaque to channel */
-	/* the following are not used at present */
 	int		speed;		/* transfer rate (bytes/second) */
+	/* the following is not used at present */
 	int		latency;	/* overhead time in milliseconds */
 };
 
---------------------------------------------------------------------
Intel Shannon Limited
Registered in Ireland
Registered Office: One Spencer Dock, North Wall Quay, Dublin 1
Registered Number: 308263
Business address: Dromore House, East Park, Shannon, Co. Clare

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11 16:33       ` PATCH Pete Popov
@ 2004-10-11 18:04         ` Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-11 18:04 UTC (permalink / raw)
  To: Pete Popov; +Cc: Atsushi Nemoto, macro, linux-mips

Pete Popov wrote:
> Atsushi Nemoto wrote:
> 
>>>>>>> On Sun, 10 Oct 2004 17:47:20 -0700, Pete Popov 
>>>>>>> <ppopov@embeddedalley.com> said:
>>
>>
>>
>> ppopov> Clearly a buglet, carried over from 2.4. That section of the
>> ppopov> code wouldn't even be compiled, since CONFIG_MIPS64 is not
>> ppopov> defined. I'll remove that and send a new patch. Anything else
>> ppopov> you see that's suspicious :)?
>>
>> Hi.  I wonder why following change is needed.
>>
>>
>>> --- include/asm-mips/page.h    20 Aug 2004 12:02:18 -0000    1.44
>>> +++ include/asm-mips/page.h    19 Sep 2004 22:51:29 -0000
>>> @@ -32,7 +32,7 @@
>>> #ifdef CONFIG_PAGE_SIZE_64KB
>>> #define PAGE_SHIFT    16
>>> #endif
>>> -#define PAGE_SIZE    (1UL << PAGE_SHIFT)
>>> +#define PAGE_SIZE    (1L << PAGE_SHIFT)
>>> #define PAGE_MASK    (~(PAGE_SIZE-1))
>>>
>>> #ifdef __KERNEL__
> 
> 
> It was related to some compiler problem I mentioned to Ralf sometime 
> ago. Perhaps it's not needed anymore, I'll take a look.

Turns out the problem is with the #define PAGE_MASK, when (1UL << 
PAGE_SHIFT) is used for PAGE_SIZE. The correct fix is already in the PPC 
tree and it doesn't use PAGE_SIZE to define PAGE_MASK. From the PPC tree:

/*
  * Subtle: this is an int (not an unsigned long) and so it
  * gets extended to 64 bits the way [we] want (i.e. with 1s).  -- paulus
  */
#define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))

I updated the patch and put a new version in my directory (v1.3).  The 
diff is:

-#define PAGE_MASK      (~(PAGE_SIZE-1))
+#define PAGE_MASK       (~((1 << PAGE_SHIFT) - 1))

I'll work on the remap_pfn_range after those bits get to kernel.org. 
That will clean up the patch nicely.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11 10:32     ` PATCH Christoph Hellwig
@ 2004-10-11 17:07       ` Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-11 17:07 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Maciej W. Rozycki, Ralf Baechle, linux-mips

Christoph Hellwig wrote:
>>===================================================================
>>RCS file: arch/mips/mm/remap.c
>>diff -N arch/mips/mm/remap.c
>>--- /dev/null	1 Jan 1970 00:00:00 -0000
>>+++ arch/mips/mm/remap.c	19 Sep 2004 22:51:21 -0000
>>@@ -0,0 +1,115 @@
>>+/*
>>+ *  arch/mips/mm/remap.c
>>+ *
>>+ *  A copy of mm/memory.c, with mods for 64 bit physical I/O addresses on
>>+ *  32 bit native word platforms.
> 
> 
> This is horrible.  Please submit any modifications you'll need over
> remap_page_pfn (as in -mm) that you still need and ensure they're
> portable.

Using remap_page_pfn would simplify the patch but that's very recent and 
I didn't even know it made it in yet. Running MIPS on top of the -mm 
tree might be a problem though, I haven't tried. I'm not sure how up to 
date MIPS is in that tree so I might have to wait until the  changes 
make it to kernel.org and then update the patch to remove remap.c and 
use remap_page_pfn instead.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11 13:53     ` PATCH Atsushi Nemoto
@ 2004-10-11 16:33       ` Pete Popov
  2004-10-11 18:04         ` PATCH Pete Popov
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2004-10-11 16:33 UTC (permalink / raw)
  To: Atsushi Nemoto; +Cc: macro, linux-mips

Atsushi Nemoto wrote:
>>>>>>On Sun, 10 Oct 2004 17:47:20 -0700, Pete Popov <ppopov@embeddedalley.com> said:
> 
> 
> ppopov> Clearly a buglet, carried over from 2.4. That section of the
> ppopov> code wouldn't even be compiled, since CONFIG_MIPS64 is not
> ppopov> defined. I'll remove that and send a new patch. Anything else
> ppopov> you see that's suspicious :)?
> 
> Hi.  I wonder why following change is needed.
> 
> 
>>--- include/asm-mips/page.h	20 Aug 2004 12:02:18 -0000	1.44
>>+++ include/asm-mips/page.h	19 Sep 2004 22:51:29 -0000
>>@@ -32,7 +32,7 @@
>> #ifdef CONFIG_PAGE_SIZE_64KB
>> #define PAGE_SHIFT	16
>> #endif
>>-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
>>+#define PAGE_SIZE	(1L << PAGE_SHIFT)
>> #define PAGE_MASK	(~(PAGE_SIZE-1))
>>
>> #ifdef __KERNEL__

It was related to some compiler problem I mentioned to Ralf sometime 
ago. Perhaps it's not needed anymore, I'll take a look.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11  7:55   ` PATCH Pete Popov
  2004-10-11 10:32     ` PATCH Christoph Hellwig
@ 2004-10-11 13:53     ` Atsushi Nemoto
  2004-10-11 16:33       ` PATCH Pete Popov
  1 sibling, 1 reply; 80+ messages in thread
From: Atsushi Nemoto @ 2004-10-11 13:53 UTC (permalink / raw)
  To: ppopov; +Cc: macro, ralf, linux-mips

>>>>> On Sun, 10 Oct 2004 17:47:20 -0700, Pete Popov <ppopov@embeddedalley.com> said:

ppopov> Clearly a buglet, carried over from 2.4. That section of the
ppopov> code wouldn't even be compiled, since CONFIG_MIPS64 is not
ppopov> defined. I'll remove that and send a new patch. Anything else
ppopov> you see that's suspicious :)?

Hi.  I wonder why following change is needed.

> --- include/asm-mips/page.h	20 Aug 2004 12:02:18 -0000	1.44
> +++ include/asm-mips/page.h	19 Sep 2004 22:51:29 -0000
> @@ -32,7 +32,7 @@
>  #ifdef CONFIG_PAGE_SIZE_64KB
>  #define PAGE_SHIFT	16
>  #endif
> -#define PAGE_SIZE	(1UL << PAGE_SHIFT)
> +#define PAGE_SIZE	(1L << PAGE_SHIFT)
>  #define PAGE_MASK	(~(PAGE_SIZE-1))
> 
>  #ifdef __KERNEL__

---
Atsushi Nemoto

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11  7:55   ` PATCH Pete Popov
@ 2004-10-11 10:32     ` Christoph Hellwig
  2004-10-11 17:07       ` PATCH Pete Popov
  2004-10-11 13:53     ` PATCH Atsushi Nemoto
  1 sibling, 1 reply; 80+ messages in thread
From: Christoph Hellwig @ 2004-10-11 10:32 UTC (permalink / raw)
  To: Pete Popov; +Cc: Maciej W. Rozycki, Ralf Baechle, linux-mips

> ===================================================================
> RCS file: arch/mips/mm/remap.c
> diff -N arch/mips/mm/remap.c
> --- /dev/null	1 Jan 1970 00:00:00 -0000
> +++ arch/mips/mm/remap.c	19 Sep 2004 22:51:21 -0000
> @@ -0,0 +1,115 @@
> +/*
> + *  arch/mips/mm/remap.c
> + *
> + *  A copy of mm/memory.c, with mods for 64 bit physical I/O addresses on
> + *  32 bit native word platforms.

This is horrible.  Please submit any modifications you'll need over
remap_page_pfn (as in -mm) that you still need and ensure they're
portable.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11  0:32 ` PATCH Maciej W. Rozycki
  2004-10-11  0:47   ` PATCH Pete Popov
@ 2004-10-11  7:55   ` Pete Popov
  2004-10-11 10:32     ` PATCH Christoph Hellwig
  2004-10-11 13:53     ` PATCH Atsushi Nemoto
  1 sibling, 2 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-11  7:55 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Ralf Baechle, linux-mips

On Sun, 2004-10-10 at 17:32, Maciej W. Rozycki wrote:
> On Mon, 10 Oct 2004, Pete Popov wrote:
> 
> > diff -u -r1.13 addrspace.h
> > --- include/asm-mips/addrspace.h	30 Nov 2003 01:52:25 -0000	1.13
> > +++ include/asm-mips/addrspace.h	19 Sep 2004 22:51:28 -0000
> > @@ -80,7 +80,11 @@
> >  #define XKSSEG			0x4000000000000000
> >  #define XKPHYS			0x8000000000000000
> >  #define XKSEG			0xc000000000000000
> > +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
> > +#define CKSEG0			0x80000000
> > +#else
> >  #define CKSEG0			0xffffffff80000000
> > +#endif
> >  #define CKSEG1			0xffffffffa0000000
> >  #define CKSSEG			0xffffffffc0000000
> >  #define CKSEG3			0xffffffffe0000000
> 
>  This looks suspicious, please explain.

Updated patch, minus above bug.

Index: arch/mips/mm/Makefile
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/Makefile,v
retrieving revision 1.68
diff -u -r1.68 Makefile
--- arch/mips/mm/Makefile	20 Jun 2004 23:52:17 -0000	1.68
+++ arch/mips/mm/Makefile	19 Sep 2004 22:51:21 -0000
@@ -41,10 +41,11 @@
 obj-$(CONFIG_CPU_RM7000)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_RM9000)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_R10000)	+= tlbex32-r4k.o
-obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-r4k.o
+obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-mips32.o
 obj-$(CONFIG_CPU_MIPS64)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_TX39XX)	+= tlbex32-r3k.o
+obj-$(CONFIG_64BIT_PHYS_ADDR)	+= remap.o
 endif
 ifdef CONFIG_MIPS64
 obj-$(CONFIG_CPU_R4300)		+= tlb64-glue-r4k.o tlbex64-r4k.o
Index: arch/mips/mm/ioremap.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/ioremap.c,v
retrieving revision 1.19
diff -u -r1.19 ioremap.c
--- arch/mips/mm/ioremap.c	19 Apr 2004 16:36:35 -0000	1.19
+++ arch/mips/mm/ioremap.c	19 Sep 2004 22:51:21 -0000
@@ -97,6 +97,15 @@
 }
 
 /*
+ * Allow physical addresses to be fixed up to help 36 bit peripherals.
+ */
+phys_t __attribute__ ((weak))
+fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+/*
  * Generic mapping function (not visible outside):
  */
 
@@ -110,7 +119,7 @@
  * caller shouldn't need to know that small detail.
  */
 
-#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL))
+#define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
 
 void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
 {
@@ -119,6 +128,8 @@
 	phys_t last_addr;
 	void * addr;
 
+	phys_addr = fixup_bigphys_addr(phys_addr, size);
+
 	/* Don't allow wraparound or zero size */
 	last_addr = phys_addr + size - 1;
 	if (!size || last_addr < phys_addr)
@@ -190,3 +201,4 @@
 
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(__iounmap);
+EXPORT_SYMBOL(fixup_bigphys_addr);
Index: arch/mips/mm/remap.c
===================================================================
RCS file: arch/mips/mm/remap.c
diff -N arch/mips/mm/remap.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/remap.c	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,115 @@
+/*
+ *  arch/mips/mm/remap.c
+ *
+ *  A copy of mm/memory.c, with mods for 64 bit physical I/O addresses on
+ *  32 bit native word platforms.
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ */
+
+
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/mman.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/rmap.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <linux/swapops.h>
+#include <linux/elf.h>
+
+
+/*
+ * maps a range of physical memory into the requested pages. the old
+ * mappings are removed. any references to nonexistent pages results
+ * in null mappings (currently treated as "copy-on-access")
+ */
+static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long end;
+	unsigned long pfn;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	pfn = phys_addr >> PAGE_SHIFT;
+	do {
+		BUG_ON(!pte_none(*pte));
+		if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
+ 			set_pte(pte, pfn_pte(pfn, prot));
+		address += PAGE_SIZE;
+		pfn++;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long base, end;
+
+	base = address & PGDIR_MASK;
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	do {
+		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
+		if (!pte)
+			return -ENOMEM;
+		remap_pte_range(pte, base + address, end - address, address + phys_addr, prot);
+		pte_unmap(pte);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+/*  Note: this is only safe if the mm semaphore is held when called. */
+int remap_page_range_high(struct vm_area_struct *vma, unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	int error = 0;
+	pgd_t * dir;
+	unsigned long beg = from;
+	unsigned long end = from + size;
+	struct mm_struct *mm = vma->vm_mm;
+
+	phys_addr -= from;
+	dir = pgd_offset(mm, from);
+	flush_cache_range(vma, beg, end);
+	if (from >= end)
+		BUG();
+
+	spin_lock(&mm->page_table_lock);
+	do {
+		pmd_t *pmd = pmd_alloc(mm, dir, from);
+		error = -ENOMEM;
+		if (!pmd)
+			break;
+		error = remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
+		if (error)
+			break;
+		from = (from + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (from && (from < end));
+	/*
+	 * Why flush? remap_pte_range has a BUG_ON for !pte_none()
+	 */
+	flush_tlb_range(vma, beg, end);
+	spin_unlock(&mm->page_table_lock);
+	return error;
+}
+
+EXPORT_SYMBOL(remap_page_range_high);
Index: arch/mips/mm/tlb-r4k.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/tlb-r4k.c,v
retrieving revision 1.38
diff -u -r1.38 tlb-r4k.c
--- arch/mips/mm/tlb-r4k.c	19 Mar 2004 04:07:59 -0000	1.38
+++ arch/mips/mm/tlb-r4k.c	19 Sep 2004 22:51:21 -0000
@@ -255,8 +255,14 @@
 	idx = read_c0_index();
 	ptep = pte_offset_map(pmdp, address);
 
-	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-	write_c0_entrylo1(pte_val(*ptep) >> 6);
+ #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ 	write_c0_entrylo0(ptep->pte_high);
+ 	ptep++;
+ 	write_c0_entrylo1(ptep->pte_high);
+#else
+  	write_c0_entrylo0(pte_val(*ptep++) >> 6);
+  	write_c0_entrylo1(pte_val(*ptep) >> 6);
+#endif
 	write_c0_entryhi(address | pid);
 	mtc0_tlbw_hazard();
 	if (idx < 0)
Index: arch/mips/mm/tlbex32-mips32.S
===================================================================
RCS file: arch/mips/mm/tlbex32-mips32.S
diff -N arch/mips/mm/tlbex32-mips32.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/tlbex32-mips32.S	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,325 @@
+/*
+ * TLB exception handling code for MIPS32 CPUs.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * Pete Popov, ppopov@pacbell.net
+ * Added 36 bit phys address support.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ */
+#include <linux/init.h>
+#include <asm/asm.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable-bits.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define TLB_OPTIMIZE /* If you are paranoid, disable this. */
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+
+/* We really only support 36 bit physical addresses on MIPS32 */
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        4 /* pte_high contains pre-shifted, ready to go entry */
+#define PTE_SIZE        8
+#define PTEP_INDX_MSK	0xff0
+#define PTE_INDX_MSK	0xff8
+#define PTE_INDX_SHIFT 9
+#define CONVERT_PTE(pte)
+#define PTE_MAKEWRITE_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, (_PAGE_VALID | _PAGE_DIRTY); \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#define PTE_MAKEVALID_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, pte, _PAGE_VALID; \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#else
+
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        0
+#define PTE_SIZE	4
+#define PTEP_INDX_MSK	0xff8
+#define PTE_INDX_MSK	0xffc
+#define PTE_INDX_SHIFT	10
+#define CONVERT_PTE(pte) srl pte, pte, 6
+#define PTE_MAKEWRITE_HIGH(pte, ptr)
+#define PTE_MAKEVALID_HIGH(pte, ptr)
+
+#endif  /* CONFIG_64BIT_PHYS_ADDR */
+
+	__INIT
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define GET_PTE_OFF(reg)
+#else
+#define GET_PTE_OFF(reg)	srl	reg, reg, 1
+#endif
+
+/*	
+ * These handlers much be written in a relocatable manner
+ * because based upon the cpu type an arbitrary one of the
+ * following pieces of code will be copied to the KSEG0
+ * vector location.
+ */
+	/* TLB refill, EXL == 0, MIPS32 version */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4000)
+	.set	mips3
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_CONTEXT
+	la	k0, pgd_current
+	srl	k1, 23
+	sll	k1, 2				# log2(sizeof(pgd_t)
+	addu	k1, k0, k1
+	lw	k1, (k1)
+#else 
+	lw	k1, pgd_current			# get pgd pointer
+#endif	
+	nop
+	mfc0	k0, CP0_BADVADDR		# Get faulting address
+	srl	k0, k0, _PGDIR_SHIFT		# get pgd only bits
+
+	sll	k0, k0, 2
+	addu	k1, k1, k0			# add in pgd offset
+	mfc0	k0, CP0_CONTEXT			# get context reg
+	lw	k1, (k1)
+	GET_PTE_OFF(k0)				# get pte offset
+	and	k0, k0, PTEP_INDX_MSK
+	addu	k1, k1, k0			# add in offset
+
+	PTE_L	k0, PTE_HALF(k1)		# get even pte
+	CONVERT_PTE(k0)
+	P_MTC0	k0, CP0_ENTRYLO0		# load it
+	PTE_L	k1, (PTE_HALF+PTE_SIZE)(k1)	# get odd pte
+	CONVERT_PTE(k1)
+	P_MTC0	k1, CP0_ENTRYLO1		# load it
+	b	1f
+	tlbwr					# write random tlb entry
+1:
+	nop
+	eret					# return from trap
+	END(except_vec0_r4000)
+
+/*
+ * These are here to avoid putting ifdefs in tlb-r4k.c
+ */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_nevada)
+	.set	mips3
+	PANIC("Nevada Exception Vec 0 called")
+	END(except_vec0_nevada)
+
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4600)
+	.set	mips3
+	PANIC("R4600 Exception Vec 0 called")
+	END(except_vec0_r4600)
+
+	__FINIT
+
+/*
+ * ABUSE of CPP macros 101.
+ *
+ * After this macro runs, the pte faulted on is
+ * in register PTE, a ptr into the table in which
+ * the pte belongs is in PTR.
+ */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, pgd_current;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);          
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, pgd_current;
+#endif
+
+#define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
+	mfc0	pte, CP0_BADVADDR; \
+	srl	pte, pte, _PGDIR_SHIFT; \
+	sll	pte, pte, 2; \
+	addu	ptr, ptr, pte; \
+	mfc0	pte, CP0_BADVADDR; \
+	lw	ptr, (ptr); \
+	srl	pte, pte, PTE_INDX_SHIFT; \
+	and	pte, pte, PTE_INDX_MSK; \
+	addu	ptr, ptr, pte; \
+	PTE_L	pte, (ptr);
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr, tmp) \
+	ori	ptr, ptr, PTE_SIZE; \
+	xori	ptr, ptr, PTE_SIZE; \
+	PTE_L	tmp, (PTE_HALF+PTE_SIZE)(ptr); \
+	CONVERT_PTE(tmp); \
+	P_MTC0	tmp, CP0_ENTRYLO1; \
+	PTE_L	ptr, PTE_HALF(ptr); \
+	CONVERT_PTE(ptr); \
+	P_MTC0	ptr, CP0_ENTRYLO0;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	STI; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_exception; \
+	 nop; \
+	.set	noat;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	PTE_S	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	PTE_S	pte, (ptr);
+
+	.set	noreorder
+
+#define R5K_HAZARD nop
+
+	.align	5
+	NESTED(handle_tlbl, PT_SIZE, sp)
+	.set	noat
+invalid_tlbl:
+#ifdef TLB_OPTIMIZE
+	/* Test present bit in entry. */
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp
+	PTE_PRESENT(k0, k1, nopage_tlbl)
+	PTE_MAKEVALID_HIGH(k0, k1)
+	PTE_MAKEVALID(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3	
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbl:
+	DO_FAULT(0)
+	END(handle_tlbl)
+
+	.align	5
+	NESTED(handle_tlbs, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+        li      k0,0
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp				# find faulting entry
+	PTE_WRITABLE(k0, k1, nopage_tlbs)
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbs:
+	DO_FAULT(1)
+	END(handle_tlbs)
+
+	.align	5
+	NESTED(handle_mod, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp					# find faulting entry
+	andi	k0, k0, _PAGE_WRITE
+	beqz	k0, nowrite_mod
+	PTE_L	k0, (k1)
+
+	/* Present and writable bits set, set accessed and dirty bits. */
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	/* Now reload the entry into the tlb. */
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nowrite_mod:
+	DO_FAULT(1)
+	END(handle_mod)
+
Index: include/asm-mips/io.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/io.h,v
retrieving revision 1.72
diff -u -r1.72 io.h
--- include/asm-mips/io.h	19 Aug 2004 15:27:41 -0000	1.72
+++ include/asm-mips/io.h	19 Sep 2004 22:51:29 -0000
@@ -171,7 +171,7 @@
 extern void * __ioremap(phys_t offset, phys_t size, unsigned long flags);
 extern void __iounmap(void *addr);
 
-static inline void * __ioremap_mode(unsigned long offset, unsigned long size,
+static inline void * __ioremap_mode(phys_t offset, unsigned long size,
 	unsigned long flags)
 {
 	if (cpu_has_64bit_addresses) {
Index: include/asm-mips/page.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/page.h,v
retrieving revision 1.44
diff -u -r1.44 page.h
--- include/asm-mips/page.h	20 Aug 2004 12:02:18 -0000	1.44
+++ include/asm-mips/page.h	19 Sep 2004 22:51:29 -0000
@@ -32,7 +32,7 @@
 #ifdef CONFIG_PAGE_SIZE_64KB
 #define PAGE_SHIFT	16
 #endif
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_SIZE	(1L << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
@@ -75,15 +75,22 @@
  * These are used to make use of C type-checking..
  */
 #ifdef CONFIG_64BIT_PHYS_ADDR
-typedef struct { unsigned long long pte; } pte_t;
+  #ifdef CONFIG_CPU_MIPS32
+    typedef struct { unsigned long pte_low, pte_high; } pte_t;
+    #define pte_val(x)    ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+  #else
+     typedef struct { unsigned long long pte; } pte_t;
+     #define pte_val(x)	((x).pte)
+  #endif
 #else
 typedef struct { unsigned long pte; } pte_t;
+#define pte_val(x)	((x).pte)
 #endif
+
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
-#define pte_val(x)	((x).pte)
 #define pmd_val(x)	((x).pmd)
 #define pgd_val(x)	((x).pgd)
 #define pgprot_val(x)	((x).pgprot)
Index: include/asm-mips/pgtable-32.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-32.h,v
retrieving revision 1.11
diff -u -r1.11 pgtable-32.h
--- include/asm-mips/pgtable-32.h	26 Jun 2004 15:15:24 -0000	1.11
+++ include/asm-mips/pgtable-32.h	19 Sep 2004 22:51:29 -0000
@@ -130,8 +130,21 @@
 static inline int pgd_present(pgd_t pgd)	{ return 1; }
 static inline void pgd_clear(pgd_t *pgdp)	{ }
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pte_pfn(x)		((unsigned long)((x).pte_high >> 6))
+static inline pte_t
+pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+	pte_t pte;
+	pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f);
+	pte.pte_low = pgprot_val(prot);
+	return pte;
+}
+
+#else
 
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
 
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
@@ -140,6 +153,7 @@
 #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #endif
+#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32) */
 
 #define __pgd_offset(address)	pgd_index(address)
 #define __pmd_offset(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
@@ -207,11 +221,19 @@
  */
 #define PTE_FILE_MAX_BITS	27
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+	/* fixme */
+#define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 0x3f))
+#define pgoff_to_pte(off) \
+ 	((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)})
+  
+#else
 #define pte_to_pgoff(_pte) \
 	((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))
 
 #define pgoff_to_pte(off) \
 	((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#endif
 
 #endif
 
Index: include/asm-mips/pgtable-bits.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-bits.h,v
retrieving revision 1.9
diff -u -r1.9 pgtable-bits.h
--- include/asm-mips/pgtable-bits.h	24 Jun 2004 20:31:11 -0000	1.9
+++ include/asm-mips/pgtable-bits.h	19 Sep 2004 22:51:29 -0000
@@ -33,6 +33,31 @@
  * unpredictable things.  The code (when it is written) to deal with
  * this problem will be in the update_mmu_cache() code for the r4k.
  */
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+
+#define _PAGE_PRESENT               (1<<6)  /* implemented in software */
+#define _PAGE_READ                  (1<<7)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<8)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<9)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<10) /* implemented in software */
+#define _PAGE_FILE                  (1<<10)  /* set:pagecache unset:swap */
+
+#define _PAGE_R4KBUG                (1<<0)  /* workaround for r4k bug  */
+#define _PAGE_GLOBAL                (1<<0)
+#define _PAGE_VALID                 (1<<1)
+#define _PAGE_SILENT_READ           (1<<1)  /* synonym                 */
+#define _PAGE_DIRTY                 (1<<2)  /* The MIPS dirty bit      */
+#define _PAGE_SILENT_WRITE          (1<<2)
+#define _CACHE_MASK                 (7<<3)
+
+/* MIPS32 defines only values 2 and 3. The rest are implementation
+ * dependent.
+ */
+#define _CACHE_UNCACHED             (2<<3)  
+#define _CACHE_CACHABLE_NONCOHERENT (3<<3) 
+
+#else
+
 #define _PAGE_PRESENT               (1<<0)  /* implemented in software */
 #define _PAGE_READ                  (1<<1)  /* implemented in software */
 #define _PAGE_WRITE                 (1<<2)  /* implemented in software */
@@ -97,6 +122,7 @@
 
 #endif
 #endif
+#endif /* defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR) */
 
 #define __READABLE	(_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
@@ -113,6 +139,10 @@
 #define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_COW
 #endif
 
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+#define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 3)
+#else
 #define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 9)
+#endif
 
 #endif /* _ASM_PGTABLE_BITS_H */
Index: include/asm-mips/pgtable.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable.h,v
retrieving revision 1.97
diff -u -r1.97 pgtable.h
--- include/asm-mips/pgtable.h	19 Jun 2004 01:39:24 -0000	1.97
+++ include/asm-mips/pgtable.h	19 Sep 2004 22:51:29 -0000
@@ -80,6 +80,34 @@
 #define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+	ptep->pte_high = pte.pte_high;
+	smp_wmb();
+	ptep->pte_low = pte.pte_low;
+	//printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
+
+	if (pte_val(pte) & _PAGE_GLOBAL) {
+		pte_t *buddy = ptep_buddy(ptep);
+		/*
+		 * Make sure the buddy is global too (if it's !none,
+		 * it better already be global)
+		 */
+		if (pte_none(*buddy))
+			buddy->pte_low |= _PAGE_GLOBAL;
+	}
+}
+
+static inline void pte_clear(pte_t *ptep)
+{
+	/* Preserve global status for the pair */
+	if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
+		set_pte(ptep, __pte(_PAGE_GLOBAL));
+	else
+		set_pte(ptep, __pte(0));
+}
+#else
 /*
  * Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -111,6 +139,7 @@
 #endif
 		set_pte(ptep, __pte(0));
 }
+#endif
 
 /*
  * (pmds are folded into pgds so this doesn't get actually called,
@@ -130,6 +159,79 @@
  * Undefined behaviour if not..
  */
 static inline int pte_user(pte_t pte)	{ BUG(); return 0; }
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline int pte_read(pte_t pte)	{ return (pte).pte_low & _PAGE_READ; }
+static inline int pte_write(pte_t pte)	{ return (pte).pte_low & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte)	{ return (pte).pte_low & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte)	{ return (pte).pte_low & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)	{ return (pte).pte_low & _PAGE_FILE; }
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_WRITE;
+	if ((pte).pte_low & _PAGE_MODIFIED) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_READ;
+	if ((pte).pte_low & _PAGE_ACCESSED) {
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_MODIFIED;
+	if ((pte).pte_low & _PAGE_WRITE) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_ACCESSED;
+	if ((pte).pte_low & _PAGE_READ)
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	return pte;
+}
+#else
 static inline int pte_read(pte_t pte)	{ return pte_val(pte) & _PAGE_READ; }
 static inline int pte_write(pte_t pte)	{ return pte_val(pte) & _PAGE_WRITE; }
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_MODIFIED; }
@@ -191,6 +293,7 @@
 		pte_val(pte) |= _PAGE_SILENT_READ;
 	return pte;
 }
+#endif
 
 /*
  * Macro to make mark a page protection value as "uncacheable".  Note
@@ -215,10 +318,20 @@
  */
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte.pte_low &= _PAGE_CHG_MASK;
+	pte.pte_low |= pgprot_val(newprot);
+	pte.pte_high |= pgprot_val(newprot) & 0x3f;
+	return pte;
+}
+#else
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
 }
+#endif
 
 
 extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
@@ -245,7 +358,27 @@
  */
 #define HAVE_ARCH_UNMAPPED_AREA
 
+#ifdef CONFIG_64BIT_PHYS_ADDR
+extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
+
+extern int remap_page_range_high(struct vm_area_struct *vma,
+		unsigned long from,
+		phys_t phys_addr,
+		unsigned long size,
+		pgprot_t prot);
+
+static inline int io_remap_page_range(struct vm_area_struct *vma,
+		unsigned long from,
+		unsigned long phys_addr,
+		unsigned long size,
+		pgprot_t prot)
+{
+	phys_t phys_addr_high = fixup_bigphys_addr(phys_addr, size);
+	return remap_page_range_high(vma, from, phys_addr_high, size, prot);
+}
+#else
 #define io_remap_page_range remap_page_range
+#endif
 
 /*
  * No page table caches to initialise

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11  0:32 ` PATCH Maciej W. Rozycki
@ 2004-10-11  0:47   ` Pete Popov
  2004-10-11  7:55   ` PATCH Pete Popov
  1 sibling, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-11  0:47 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Ralf Baechle, linux-mips

Maciej W. Rozycki wrote:
> On Mon, 10 Oct 2004, Pete Popov wrote:
> 
> 
>>diff -u -r1.13 addrspace.h
>>--- include/asm-mips/addrspace.h	30 Nov 2003 01:52:25 -0000	1.13
>>+++ include/asm-mips/addrspace.h	19 Sep 2004 22:51:28 -0000
>>@@ -80,7 +80,11 @@
>> #define XKSSEG			0x4000000000000000
>> #define XKPHYS			0x8000000000000000
>> #define XKSEG			0xc000000000000000
>>+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
>>+#define CKSEG0			0x80000000
>>+#else
>> #define CKSEG0			0xffffffff80000000
>>+#endif
>> #define CKSEG1			0xffffffffa0000000
>> #define CKSSEG			0xffffffffc0000000
>> #define CKSEG3			0xffffffffe0000000
> 
> 
>  This looks suspicious, please explain.

Clearly a buglet, carried over from 2.4. That section of the code 
wouldn't even be compiled, since CONFIG_MIPS64 is not defined. I'll 
remove that and send a new patch. Anything else you see that's 
suspicious :)?

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11  0:25       ` PATCH Maciej W. Rozycki
@ 2004-10-11  0:39         ` Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-11  0:39 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Geert Uytterhoeven, linux-mips

Maciej W. Rozycki wrote:
> On Sun, 10 Oct 2004, Pete Popov wrote:
> 
> 
>>>If not, why not use a data type that covers
>>>valid offsets only when passing addresses to bus access functions? 
>>
>>The attribute and memory pcmcia addresses are just stored in these 
>>variables, and then the upper pcmcia stack layer calls ioremap on these 
>>addresses. Thus, you need the 36 bit I/O address patch, as well as the 
>>tiny pcmcia patch.
>>
>>The pcmcia I/O address is ioremapped at the socket driver level. If that 
>>was the case with the mem and attribute addresses, I wouldn't need this 
>>64 bit pcmcia patch. But since it's the upper pcmcia layer that ioremaps 
>>these addresses, I need to store tham in 64 bit types.
> 
> 
>  OK, but then phys_t should be used for ioaddr_t universally, shouldn't
> it?  Any architecture can have the controller seen in a 64-bit memory
> space, after all.

Perhaps, but when I tried that in 2.4, I got rejected. Matt had an idea 
that works for both, mips and ppc, since the 36 bit fixup_bigphys_addr 
routine is very similar. I think I'll pursue that instead, since we 
already have that routine as part of the pci address support. Thus, I 
won't have to make pcmcia changes to common files, and no more 
64bit_pcmcia.patch hanging around in my directory.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-11  0:01 PATCH Pete Popov
@ 2004-10-11  0:32 ` Maciej W. Rozycki
  2004-10-11  0:47   ` PATCH Pete Popov
  2004-10-11  7:55   ` PATCH Pete Popov
  0 siblings, 2 replies; 80+ messages in thread
From: Maciej W. Rozycki @ 2004-10-11  0:32 UTC (permalink / raw)
  To: Pete Popov; +Cc: Ralf Baechle, linux-mips

On Mon, 10 Oct 2004, Pete Popov wrote:

> diff -u -r1.13 addrspace.h
> --- include/asm-mips/addrspace.h	30 Nov 2003 01:52:25 -0000	1.13
> +++ include/asm-mips/addrspace.h	19 Sep 2004 22:51:28 -0000
> @@ -80,7 +80,11 @@
>  #define XKSSEG			0x4000000000000000
>  #define XKPHYS			0x8000000000000000
>  #define XKSEG			0xc000000000000000
> +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
> +#define CKSEG0			0x80000000
> +#else
>  #define CKSEG0			0xffffffff80000000
> +#endif
>  #define CKSEG1			0xffffffffa0000000
>  #define CKSSEG			0xffffffffc0000000
>  #define CKSEG3			0xffffffffe0000000

 This looks suspicious, please explain.

  Maciej

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-10 22:50     ` PATCH Pete Popov
@ 2004-10-11  0:25       ` Maciej W. Rozycki
  2004-10-11  0:39         ` PATCH Pete Popov
  0 siblings, 1 reply; 80+ messages in thread
From: Maciej W. Rozycki @ 2004-10-11  0:25 UTC (permalink / raw)
  To: Pete Popov; +Cc: Geert Uytterhoeven, linux-mips

On Sun, 10 Oct 2004, Pete Popov wrote:

> > If not, why not use a data type that covers
> > valid offsets only when passing addresses to bus access functions? 
> 
> The attribute and memory pcmcia addresses are just stored in these 
> variables, and then the upper pcmcia stack layer calls ioremap on these 
> addresses. Thus, you need the 36 bit I/O address patch, as well as the 
> tiny pcmcia patch.
> 
> The pcmcia I/O address is ioremapped at the socket driver level. If that 
> was the case with the mem and attribute addresses, I wouldn't need this 
> 64 bit pcmcia patch. But since it's the upper pcmcia layer that ioremaps 
> these addresses, I need to store tham in 64 bit types.

 OK, but then phys_t should be used for ioaddr_t universally, shouldn't
it?  Any architecture can have the controller seen in a 64-bit memory
space, after all.

  Maciej

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2004-10-11  0:01 Pete Popov
  2004-10-11  0:32 ` PATCH Maciej W. Rozycki
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2004-10-11  0:01 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Ralf,

Sorry, one more update to the 36 bit patch. The only difference is that
I removed the hunk that updates arch/mips/au1000/common/setup.c because
I'll apply that part myself, and then make other updates to setup.c that
would then conflict with the patch I sent you. This is the final version
you can apply ;)

Pete


Index: arch/mips/mm/Makefile
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/Makefile,v
retrieving revision 1.68
diff -u -r1.68 Makefile
--- arch/mips/mm/Makefile	20 Jun 2004 23:52:17 -0000	1.68
+++ arch/mips/mm/Makefile	19 Sep 2004 22:51:21 -0000
@@ -41,10 +41,11 @@
 obj-$(CONFIG_CPU_RM7000)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_RM9000)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_R10000)	+= tlbex32-r4k.o
-obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-r4k.o
+obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-mips32.o
 obj-$(CONFIG_CPU_MIPS64)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_TX39XX)	+= tlbex32-r3k.o
+obj-$(CONFIG_64BIT_PHYS_ADDR)	+= remap.o
 endif
 ifdef CONFIG_MIPS64
 obj-$(CONFIG_CPU_R4300)		+= tlb64-glue-r4k.o tlbex64-r4k.o
Index: arch/mips/mm/ioremap.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/ioremap.c,v
retrieving revision 1.19
diff -u -r1.19 ioremap.c
--- arch/mips/mm/ioremap.c	19 Apr 2004 16:36:35 -0000	1.19
+++ arch/mips/mm/ioremap.c	19 Sep 2004 22:51:21 -0000
@@ -97,6 +97,15 @@
 }
 
 /*
+ * Allow physical addresses to be fixed up to help 36 bit peripherals.
+ */
+phys_t __attribute__ ((weak))
+fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+/*
  * Generic mapping function (not visible outside):
  */
 
@@ -110,7 +119,7 @@
  * caller shouldn't need to know that small detail.
  */
 
-#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL))
+#define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
 
 void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
 {
@@ -119,6 +128,8 @@
 	phys_t last_addr;
 	void * addr;
 
+	phys_addr = fixup_bigphys_addr(phys_addr, size);
+
 	/* Don't allow wraparound or zero size */
 	last_addr = phys_addr + size - 1;
 	if (!size || last_addr < phys_addr)
@@ -190,3 +201,4 @@
 
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(__iounmap);
+EXPORT_SYMBOL(fixup_bigphys_addr);
Index: arch/mips/mm/remap.c
===================================================================
RCS file: arch/mips/mm/remap.c
diff -N arch/mips/mm/remap.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/remap.c	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,115 @@
+/*
+ *  arch/mips/mm/remap.c
+ *
+ *  A copy of mm/memory.c, with mods for 64 bit physical I/O addresses on
+ *  32 bit native word platforms.
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ */
+
+
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/mman.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/rmap.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <linux/swapops.h>
+#include <linux/elf.h>
+
+
+/*
+ * maps a range of physical memory into the requested pages. the old
+ * mappings are removed. any references to nonexistent pages results
+ * in null mappings (currently treated as "copy-on-access")
+ */
+static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long end;
+	unsigned long pfn;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	pfn = phys_addr >> PAGE_SHIFT;
+	do {
+		BUG_ON(!pte_none(*pte));
+		if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
+ 			set_pte(pte, pfn_pte(pfn, prot));
+		address += PAGE_SIZE;
+		pfn++;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long base, end;
+
+	base = address & PGDIR_MASK;
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	do {
+		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
+		if (!pte)
+			return -ENOMEM;
+		remap_pte_range(pte, base + address, end - address, address + phys_addr, prot);
+		pte_unmap(pte);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+/*  Note: this is only safe if the mm semaphore is held when called. */
+int remap_page_range_high(struct vm_area_struct *vma, unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	int error = 0;
+	pgd_t * dir;
+	unsigned long beg = from;
+	unsigned long end = from + size;
+	struct mm_struct *mm = vma->vm_mm;
+
+	phys_addr -= from;
+	dir = pgd_offset(mm, from);
+	flush_cache_range(vma, beg, end);
+	if (from >= end)
+		BUG();
+
+	spin_lock(&mm->page_table_lock);
+	do {
+		pmd_t *pmd = pmd_alloc(mm, dir, from);
+		error = -ENOMEM;
+		if (!pmd)
+			break;
+		error = remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
+		if (error)
+			break;
+		from = (from + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (from && (from < end));
+	/*
+	 * Why flush? remap_pte_range has a BUG_ON for !pte_none()
+	 */
+	flush_tlb_range(vma, beg, end);
+	spin_unlock(&mm->page_table_lock);
+	return error;
+}
+
+EXPORT_SYMBOL(remap_page_range_high);
Index: arch/mips/mm/tlb-r4k.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/tlb-r4k.c,v
retrieving revision 1.38
diff -u -r1.38 tlb-r4k.c
--- arch/mips/mm/tlb-r4k.c	19 Mar 2004 04:07:59 -0000	1.38
+++ arch/mips/mm/tlb-r4k.c	19 Sep 2004 22:51:21 -0000
@@ -255,8 +255,14 @@
 	idx = read_c0_index();
 	ptep = pte_offset_map(pmdp, address);
 
-	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-	write_c0_entrylo1(pte_val(*ptep) >> 6);
+ #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ 	write_c0_entrylo0(ptep->pte_high);
+ 	ptep++;
+ 	write_c0_entrylo1(ptep->pte_high);
+#else
+  	write_c0_entrylo0(pte_val(*ptep++) >> 6);
+  	write_c0_entrylo1(pte_val(*ptep) >> 6);
+#endif
 	write_c0_entryhi(address | pid);
 	mtc0_tlbw_hazard();
 	if (idx < 0)
Index: arch/mips/mm/tlbex32-mips32.S
===================================================================
RCS file: arch/mips/mm/tlbex32-mips32.S
diff -N arch/mips/mm/tlbex32-mips32.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/tlbex32-mips32.S	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,325 @@
+/*
+ * TLB exception handling code for MIPS32 CPUs.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * Pete Popov, ppopov@pacbell.net
+ * Added 36 bit phys address support.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ */
+#include <linux/init.h>
+#include <asm/asm.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable-bits.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define TLB_OPTIMIZE /* If you are paranoid, disable this. */
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+
+/* We really only support 36 bit physical addresses on MIPS32 */
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        4 /* pte_high contains pre-shifted, ready to go entry */
+#define PTE_SIZE        8
+#define PTEP_INDX_MSK	0xff0
+#define PTE_INDX_MSK	0xff8
+#define PTE_INDX_SHIFT 9
+#define CONVERT_PTE(pte)
+#define PTE_MAKEWRITE_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, (_PAGE_VALID | _PAGE_DIRTY); \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#define PTE_MAKEVALID_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, pte, _PAGE_VALID; \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#else
+
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        0
+#define PTE_SIZE	4
+#define PTEP_INDX_MSK	0xff8
+#define PTE_INDX_MSK	0xffc
+#define PTE_INDX_SHIFT	10
+#define CONVERT_PTE(pte) srl pte, pte, 6
+#define PTE_MAKEWRITE_HIGH(pte, ptr)
+#define PTE_MAKEVALID_HIGH(pte, ptr)
+
+#endif  /* CONFIG_64BIT_PHYS_ADDR */
+
+	__INIT
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define GET_PTE_OFF(reg)
+#else
+#define GET_PTE_OFF(reg)	srl	reg, reg, 1
+#endif
+
+/*	
+ * These handlers much be written in a relocatable manner
+ * because based upon the cpu type an arbitrary one of the
+ * following pieces of code will be copied to the KSEG0
+ * vector location.
+ */
+	/* TLB refill, EXL == 0, MIPS32 version */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4000)
+	.set	mips3
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_CONTEXT
+	la	k0, pgd_current
+	srl	k1, 23
+	sll	k1, 2				# log2(sizeof(pgd_t)
+	addu	k1, k0, k1
+	lw	k1, (k1)
+#else 
+	lw	k1, pgd_current			# get pgd pointer
+#endif	
+	nop
+	mfc0	k0, CP0_BADVADDR		# Get faulting address
+	srl	k0, k0, _PGDIR_SHIFT		# get pgd only bits
+
+	sll	k0, k0, 2
+	addu	k1, k1, k0			# add in pgd offset
+	mfc0	k0, CP0_CONTEXT			# get context reg
+	lw	k1, (k1)
+	GET_PTE_OFF(k0)				# get pte offset
+	and	k0, k0, PTEP_INDX_MSK
+	addu	k1, k1, k0			# add in offset
+
+	PTE_L	k0, PTE_HALF(k1)		# get even pte
+	CONVERT_PTE(k0)
+	P_MTC0	k0, CP0_ENTRYLO0		# load it
+	PTE_L	k1, (PTE_HALF+PTE_SIZE)(k1)	# get odd pte
+	CONVERT_PTE(k1)
+	P_MTC0	k1, CP0_ENTRYLO1		# load it
+	b	1f
+	tlbwr					# write random tlb entry
+1:
+	nop
+	eret					# return from trap
+	END(except_vec0_r4000)
+
+/*
+ * These are here to avoid putting ifdefs in tlb-r4k.c
+ */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_nevada)
+	.set	mips3
+	PANIC("Nevada Exception Vec 0 called")
+	END(except_vec0_nevada)
+
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4600)
+	.set	mips3
+	PANIC("R4600 Exception Vec 0 called")
+	END(except_vec0_r4600)
+
+	__FINIT
+
+/*
+ * ABUSE of CPP macros 101.
+ *
+ * After this macro runs, the pte faulted on is
+ * in register PTE, a ptr into the table in which
+ * the pte belongs is in PTR.
+ */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, pgd_current;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);          
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, pgd_current;
+#endif
+
+#define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
+	mfc0	pte, CP0_BADVADDR; \
+	srl	pte, pte, _PGDIR_SHIFT; \
+	sll	pte, pte, 2; \
+	addu	ptr, ptr, pte; \
+	mfc0	pte, CP0_BADVADDR; \
+	lw	ptr, (ptr); \
+	srl	pte, pte, PTE_INDX_SHIFT; \
+	and	pte, pte, PTE_INDX_MSK; \
+	addu	ptr, ptr, pte; \
+	PTE_L	pte, (ptr);
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr, tmp) \
+	ori	ptr, ptr, PTE_SIZE; \
+	xori	ptr, ptr, PTE_SIZE; \
+	PTE_L	tmp, (PTE_HALF+PTE_SIZE)(ptr); \
+	CONVERT_PTE(tmp); \
+	P_MTC0	tmp, CP0_ENTRYLO1; \
+	PTE_L	ptr, PTE_HALF(ptr); \
+	CONVERT_PTE(ptr); \
+	P_MTC0	ptr, CP0_ENTRYLO0;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	STI; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_exception; \
+	 nop; \
+	.set	noat;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	PTE_S	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	PTE_S	pte, (ptr);
+
+	.set	noreorder
+
+#define R5K_HAZARD nop
+
+	.align	5
+	NESTED(handle_tlbl, PT_SIZE, sp)
+	.set	noat
+invalid_tlbl:
+#ifdef TLB_OPTIMIZE
+	/* Test present bit in entry. */
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp
+	PTE_PRESENT(k0, k1, nopage_tlbl)
+	PTE_MAKEVALID_HIGH(k0, k1)
+	PTE_MAKEVALID(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3	
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbl:
+	DO_FAULT(0)
+	END(handle_tlbl)
+
+	.align	5
+	NESTED(handle_tlbs, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+        li      k0,0
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp				# find faulting entry
+	PTE_WRITABLE(k0, k1, nopage_tlbs)
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbs:
+	DO_FAULT(1)
+	END(handle_tlbs)
+
+	.align	5
+	NESTED(handle_mod, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp					# find faulting entry
+	andi	k0, k0, _PAGE_WRITE
+	beqz	k0, nowrite_mod
+	PTE_L	k0, (k1)
+
+	/* Present and writable bits set, set accessed and dirty bits. */
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	/* Now reload the entry into the tlb. */
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nowrite_mod:
+	DO_FAULT(1)
+	END(handle_mod)
+
Index: include/asm-mips/addrspace.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/addrspace.h,v
retrieving revision 1.13
diff -u -r1.13 addrspace.h
--- include/asm-mips/addrspace.h	30 Nov 2003 01:52:25 -0000	1.13
+++ include/asm-mips/addrspace.h	19 Sep 2004 22:51:28 -0000
@@ -80,7 +80,11 @@
 #define XKSSEG			0x4000000000000000
 #define XKPHYS			0x8000000000000000
 #define XKSEG			0xc000000000000000
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#define CKSEG0			0x80000000
+#else
 #define CKSEG0			0xffffffff80000000
+#endif
 #define CKSEG1			0xffffffffa0000000
 #define CKSSEG			0xffffffffc0000000
 #define CKSEG3			0xffffffffe0000000
Index: include/asm-mips/io.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/io.h,v
retrieving revision 1.72
diff -u -r1.72 io.h
--- include/asm-mips/io.h	19 Aug 2004 15:27:41 -0000	1.72
+++ include/asm-mips/io.h	19 Sep 2004 22:51:29 -0000
@@ -171,7 +171,7 @@
 extern void * __ioremap(phys_t offset, phys_t size, unsigned long flags);
 extern void __iounmap(void *addr);
 
-static inline void * __ioremap_mode(unsigned long offset, unsigned long size,
+static inline void * __ioremap_mode(phys_t offset, unsigned long size,
 	unsigned long flags)
 {
 	if (cpu_has_64bit_addresses) {
Index: include/asm-mips/page.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/page.h,v
retrieving revision 1.44
diff -u -r1.44 page.h
--- include/asm-mips/page.h	20 Aug 2004 12:02:18 -0000	1.44
+++ include/asm-mips/page.h	19 Sep 2004 22:51:29 -0000
@@ -32,7 +32,7 @@
 #ifdef CONFIG_PAGE_SIZE_64KB
 #define PAGE_SHIFT	16
 #endif
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_SIZE	(1L << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
@@ -75,15 +75,22 @@
  * These are used to make use of C type-checking..
  */
 #ifdef CONFIG_64BIT_PHYS_ADDR
-typedef struct { unsigned long long pte; } pte_t;
+  #ifdef CONFIG_CPU_MIPS32
+    typedef struct { unsigned long pte_low, pte_high; } pte_t;
+    #define pte_val(x)    ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+  #else
+     typedef struct { unsigned long long pte; } pte_t;
+     #define pte_val(x)	((x).pte)
+  #endif
 #else
 typedef struct { unsigned long pte; } pte_t;
+#define pte_val(x)	((x).pte)
 #endif
+
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
-#define pte_val(x)	((x).pte)
 #define pmd_val(x)	((x).pmd)
 #define pgd_val(x)	((x).pgd)
 #define pgprot_val(x)	((x).pgprot)
Index: include/asm-mips/pgtable-32.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-32.h,v
retrieving revision 1.11
diff -u -r1.11 pgtable-32.h
--- include/asm-mips/pgtable-32.h	26 Jun 2004 15:15:24 -0000	1.11
+++ include/asm-mips/pgtable-32.h	19 Sep 2004 22:51:29 -0000
@@ -130,8 +130,21 @@
 static inline int pgd_present(pgd_t pgd)	{ return 1; }
 static inline void pgd_clear(pgd_t *pgdp)	{ }
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pte_pfn(x)		((unsigned long)((x).pte_high >> 6))
+static inline pte_t
+pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+	pte_t pte;
+	pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f);
+	pte.pte_low = pgprot_val(prot);
+	return pte;
+}
+
+#else
 
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
 
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
@@ -140,6 +153,7 @@
 #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #endif
+#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32) */
 
 #define __pgd_offset(address)	pgd_index(address)
 #define __pmd_offset(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
@@ -207,11 +221,19 @@
  */
 #define PTE_FILE_MAX_BITS	27
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+	/* fixme */
+#define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 0x3f))
+#define pgoff_to_pte(off) \
+ 	((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)})
+  
+#else
 #define pte_to_pgoff(_pte) \
 	((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))
 
 #define pgoff_to_pte(off) \
 	((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#endif
 
 #endif
 
Index: include/asm-mips/pgtable-bits.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-bits.h,v
retrieving revision 1.9
diff -u -r1.9 pgtable-bits.h
--- include/asm-mips/pgtable-bits.h	24 Jun 2004 20:31:11 -0000	1.9
+++ include/asm-mips/pgtable-bits.h	19 Sep 2004 22:51:29 -0000
@@ -33,6 +33,31 @@
  * unpredictable things.  The code (when it is written) to deal with
  * this problem will be in the update_mmu_cache() code for the r4k.
  */
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+
+#define _PAGE_PRESENT               (1<<6)  /* implemented in software */
+#define _PAGE_READ                  (1<<7)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<8)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<9)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<10) /* implemented in software */
+#define _PAGE_FILE                  (1<<10)  /* set:pagecache unset:swap */
+
+#define _PAGE_R4KBUG                (1<<0)  /* workaround for r4k bug  */
+#define _PAGE_GLOBAL                (1<<0)
+#define _PAGE_VALID                 (1<<1)
+#define _PAGE_SILENT_READ           (1<<1)  /* synonym                 */
+#define _PAGE_DIRTY                 (1<<2)  /* The MIPS dirty bit      */
+#define _PAGE_SILENT_WRITE          (1<<2)
+#define _CACHE_MASK                 (7<<3)
+
+/* MIPS32 defines only values 2 and 3. The rest are implementation
+ * dependent.
+ */
+#define _CACHE_UNCACHED             (2<<3)  
+#define _CACHE_CACHABLE_NONCOHERENT (3<<3) 
+
+#else
+
 #define _PAGE_PRESENT               (1<<0)  /* implemented in software */
 #define _PAGE_READ                  (1<<1)  /* implemented in software */
 #define _PAGE_WRITE                 (1<<2)  /* implemented in software */
@@ -97,6 +122,7 @@
 
 #endif
 #endif
+#endif /* defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR) */
 
 #define __READABLE	(_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
@@ -113,6 +139,10 @@
 #define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_COW
 #endif
 
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+#define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 3)
+#else
 #define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 9)
+#endif
 
 #endif /* _ASM_PGTABLE_BITS_H */
Index: include/asm-mips/pgtable.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable.h,v
retrieving revision 1.97
diff -u -r1.97 pgtable.h
--- include/asm-mips/pgtable.h	19 Jun 2004 01:39:24 -0000	1.97
+++ include/asm-mips/pgtable.h	19 Sep 2004 22:51:29 -0000
@@ -80,6 +80,34 @@
 #define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+	ptep->pte_high = pte.pte_high;
+	smp_wmb();
+	ptep->pte_low = pte.pte_low;
+	//printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
+
+	if (pte_val(pte) & _PAGE_GLOBAL) {
+		pte_t *buddy = ptep_buddy(ptep);
+		/*
+		 * Make sure the buddy is global too (if it's !none,
+		 * it better already be global)
+		 */
+		if (pte_none(*buddy))
+			buddy->pte_low |= _PAGE_GLOBAL;
+	}
+}
+
+static inline void pte_clear(pte_t *ptep)
+{
+	/* Preserve global status for the pair */
+	if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
+		set_pte(ptep, __pte(_PAGE_GLOBAL));
+	else
+		set_pte(ptep, __pte(0));
+}
+#else
 /*
  * Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -111,6 +139,7 @@
 #endif
 		set_pte(ptep, __pte(0));
 }
+#endif
 
 /*
  * (pmds are folded into pgds so this doesn't get actually called,
@@ -130,6 +159,79 @@
  * Undefined behaviour if not..
  */
 static inline int pte_user(pte_t pte)	{ BUG(); return 0; }
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline int pte_read(pte_t pte)	{ return (pte).pte_low & _PAGE_READ; }
+static inline int pte_write(pte_t pte)	{ return (pte).pte_low & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte)	{ return (pte).pte_low & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte)	{ return (pte).pte_low & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)	{ return (pte).pte_low & _PAGE_FILE; }
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_WRITE;
+	if ((pte).pte_low & _PAGE_MODIFIED) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_READ;
+	if ((pte).pte_low & _PAGE_ACCESSED) {
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_MODIFIED;
+	if ((pte).pte_low & _PAGE_WRITE) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_ACCESSED;
+	if ((pte).pte_low & _PAGE_READ)
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	return pte;
+}
+#else
 static inline int pte_read(pte_t pte)	{ return pte_val(pte) & _PAGE_READ; }
 static inline int pte_write(pte_t pte)	{ return pte_val(pte) & _PAGE_WRITE; }
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_MODIFIED; }
@@ -191,6 +293,7 @@
 		pte_val(pte) |= _PAGE_SILENT_READ;
 	return pte;
 }
+#endif
 
 /*
  * Macro to make mark a page protection value as "uncacheable".  Note
@@ -215,10 +318,20 @@
  */
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte.pte_low &= _PAGE_CHG_MASK;
+	pte.pte_low |= pgprot_val(newprot);
+	pte.pte_high |= pgprot_val(newprot) & 0x3f;
+	return pte;
+}
+#else
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
 }
+#endif
 
 
 extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
@@ -245,7 +358,27 @@
  */
 #define HAVE_ARCH_UNMAPPED_AREA
 
+#ifdef CONFIG_64BIT_PHYS_ADDR
+extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
+
+extern int remap_page_range_high(struct vm_area_struct *vma,
+		unsigned long from,
+		phys_t phys_addr,
+		unsigned long size,
+		pgprot_t prot);
+
+static inline int io_remap_page_range(struct vm_area_struct *vma,
+		unsigned long from,
+		unsigned long phys_addr,
+		unsigned long size,
+		pgprot_t prot)
+{
+	phys_t phys_addr_high = fixup_bigphys_addr(phys_addr, size);
+	return remap_page_range_high(vma, from, phys_addr_high, size, prot);
+}
+#else
 #define io_remap_page_range remap_page_range
+#endif
 
 /*
  * No page table caches to initialise

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2004-10-10 23:43 Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-10 23:43 UTC (permalink / raw)
  To: linux-mips

Ralf,

Here is another patch for consideration. No updates are needed to other
platforms that need/require the obsolete ide probing. When enabled, the
patch gets rid of all the probing of obsolete ide devices.

diff -Naur --exclude=CVS linux-2.6-orig/arch/mips/Kconfig linux-2.6-dev/arch/mips/Kconfig
--- linux-2.6-orig/arch/mips/Kconfig	2004-09-25 23:33:01.000000000 -0700
+++ linux-2.6-dev/arch/mips/Kconfig	2004-10-10 11:41:45.000000000 -0700
@@ -577,6 +577,7 @@
 	depends on SOC_AU1500
 	select DMA_NONCOHERENT
 	select HW_HAS_PCI
+	select MIPS_DISABLE_OBSOLETE_IDE
 
 config MIPS_DB1550
 	bool "DB1550 board"
@@ -896,6 +897,9 @@
 	depends on LASAT
 	default y
 
+config MIPS_DISABLE_OBSOLETE_IDE
+	bool
+
 config CPU_LITTLE_ENDIAN
 	bool "Generate little endian code"
 	default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || MACH_DECSTATION || HP_LASERJET || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || SOC_AU1X00 || NEC_OSPREY || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA
diff -Naur --exclude=CVS linux-2.6-orig/include/asm-mips/mach-generic/ide.h linux-2.6-dev/include/asm-mips/mach-generic/ide.h
--- linux-2.6-orig/include/asm-mips/mach-generic/ide.h	2004-06-09 07:12:13.000000000 -0700
+++ linux-2.6-dev/include/asm-mips/mach-generic/ide.h	2004-10-10 11:44:22.000000000 -0700
@@ -20,6 +20,7 @@
 # endif
 #endif
 
+#ifndef CONFIG_MIPS_DISABLE_OBSOLETE_IDE
 #define IDE_ARCH_OBSOLETE_DEFAULTS
 
 static inline int ide_default_irq(unsigned long base)
@@ -49,6 +50,7 @@
 			return 0;
 	}
 }
+#endif /* CONFIG_MIPS_DISABLE_OBSOLETE_IDE */
 
 #define IDE_ARCH_OBSOLETE_INIT
 #define ide_default_io_ctl(base)	((base) + 0x206) /* obsolete */

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-10 19:33   ` PATCH Matt Porter
  2004-10-10 22:52     ` PATCH Pete Popov
@ 2004-10-10 23:41     ` Pete Popov
  1 sibling, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-10 23:41 UTC (permalink / raw)
  To: Matt Porter; +Cc: Geert Uytterhoeven, linux-mips


> To answer Pete's original question, I would suggest posting the patch
> to http://lists.infradead.org/mailman/listinfo/linux-pcmcia which is
> where PCMCIA subsystem development conversations are taking place. It
> might be good to cc: rmk since he's been the de facto PCMCIA
> maintainer.

Or, we'll go with your idea we just discussed :) No need for the 64 bit 
pcmcia patch in that case.

I'll make the updates in the next few hours and test them.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-10 19:33   ` PATCH Matt Porter
@ 2004-10-10 22:52     ` Pete Popov
  2004-10-10 23:41     ` PATCH Pete Popov
  1 sibling, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-10 22:52 UTC (permalink / raw)
  To: Matt Porter; +Cc: Geert Uytterhoeven, linux-mips

Matt Porter wrote:
> On Sun, Oct 10, 2004 at 08:01:28PM +0200, Geert Uytterhoeven wrote:
> 
>>On Sun, 10 Oct 2004, Pete Popov wrote:
>>
>>>Ralf, or anyone else, any suggestions on how to get a patch like the one
>>>below accepted in 2.6? It's needed due to the 36 bit address of the
>>>pcmcia controller on the Au1x CPUs.
>>
>>Perhaps you can ask the PPC people? Book E PPC has 36-bit I/O as well.
> 
>  
> FWIW, it's specifically PPC440 cores that have a 36-bit address space.
> It should be noted that nobody has as of yet expressed public interest
> in having PCMCIA working on PPC440. I just ran into a person with a
> custom board last week interfacing a CF card that would need a similar
> patch to handle ppc's phys_addr_t.
> 
> To answer Pete's original question, I would suggest posting the patch
> to http://lists.infradead.org/mailman/listinfo/linux-pcmcia which is
> where PCMCIA subsystem development conversations are taking place. It
> might be good to cc: rmk since he's been the de facto PCMCIA
> maintainer.

I'll try that, thanks. If more SOCs needed this feature, it might have 
been possible to get it accepted in 2.4 a long time ago.  With the 
PPC440, now it's not only the Au1x that needs the patch.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-10 19:11   ` PATCH Maciej W. Rozycki
@ 2004-10-10 22:50     ` Pete Popov
  2004-10-11  0:25       ` PATCH Maciej W. Rozycki
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2004-10-10 22:50 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: Geert Uytterhoeven, linux-mips

Maciej W. Rozycki wrote:
> On Sun, 10 Oct 2004, Geert Uytterhoeven wrote:
> 
> 
>>>Ralf, or anyone else, any suggestions on how to get a patch like the one
>>>below accepted in 2.6? It's needed due to the 36 bit address of the
>>>pcmcia controller on the Au1x CPUs.
>>
>>Perhaps you can ask the PPC people? Book E PPC has 36-bit I/O as well.
> 
> 
>  Using 36-bit pointers for PCMCIA seems questionable to me -- does the bus
> support such wide addresses?  

Sort of. The internal CPU bus has a 36 bit chip select. You never see 
the 36 bit phys address on the bus, but the PCI, external LCD, and 
pcmcia addresses are 36 bit. That's the reason for the 36 bit I/O 
address patch I sent last night.

> If not, why not use a data type that covers
> valid offsets only when passing addresses to bus access functions? 

The attribute and memory pcmcia addresses are just stored in these 
variables, and then the upper pcmcia stack layer calls ioremap on these 
addresses. Thus, you need the 36 bit I/O address patch, as well as the 
tiny pcmcia patch.

The pcmcia I/O address is ioremapped at the socket driver level. If that 
was the case with the mem and attribute addresses, I wouldn't need this 
64 bit pcmcia patch. But since it's the upper pcmcia layer that ioremaps 
these addresses, I need to store tham in 64 bit types.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-10 18:01 ` PATCH Geert Uytterhoeven
  2004-10-10 19:11   ` PATCH Maciej W. Rozycki
@ 2004-10-10 19:33   ` Matt Porter
  2004-10-10 22:52     ` PATCH Pete Popov
  2004-10-10 23:41     ` PATCH Pete Popov
  1 sibling, 2 replies; 80+ messages in thread
From: Matt Porter @ 2004-10-10 19:33 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Pete Popov, linux-mips

On Sun, Oct 10, 2004 at 08:01:28PM +0200, Geert Uytterhoeven wrote:
> On Sun, 10 Oct 2004, Pete Popov wrote:
> > Ralf, or anyone else, any suggestions on how to get a patch like the one
> > below accepted in 2.6? It's needed due to the 36 bit address of the
> > pcmcia controller on the Au1x CPUs.
> 
> Perhaps you can ask the PPC people? Book E PPC has 36-bit I/O as well.
 
FWIW, it's specifically PPC440 cores that have a 36-bit address space.
It should be noted that nobody has as of yet expressed public interest
in having PCMCIA working on PPC440. I just ran into a person with a
custom board last week interfacing a CF card that would need a similar
patch to handle ppc's phys_addr_t.

To answer Pete's original question, I would suggest posting the patch
to http://lists.infradead.org/mailman/listinfo/linux-pcmcia which is
where PCMCIA subsystem development conversations are taking place. It
might be good to cc: rmk since he's been the de facto PCMCIA
maintainer.

-Matt

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-10 18:01 ` PATCH Geert Uytterhoeven
@ 2004-10-10 19:11   ` Maciej W. Rozycki
  2004-10-10 22:50     ` PATCH Pete Popov
  2004-10-10 19:33   ` PATCH Matt Porter
  1 sibling, 1 reply; 80+ messages in thread
From: Maciej W. Rozycki @ 2004-10-10 19:11 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Pete Popov, linux-mips

On Sun, 10 Oct 2004, Geert Uytterhoeven wrote:

> > Ralf, or anyone else, any suggestions on how to get a patch like the one
> > below accepted in 2.6? It's needed due to the 36 bit address of the
> > pcmcia controller on the Au1x CPUs.
> 
> Perhaps you can ask the PPC people? Book E PPC has 36-bit I/O as well.

 Using 36-bit pointers for PCMCIA seems questionable to me -- does the bus
support such wide addresses?  If not, why not use a data type that covers
valid offsets only when passing addresses to bus access functions?  In
particular, the range of offsets (the data type used) shouldn't depend on
the processor type, should it?

  Maciej

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-10-10 17:17 PATCH Pete Popov
@ 2004-10-10 18:01 ` Geert Uytterhoeven
  2004-10-10 19:11   ` PATCH Maciej W. Rozycki
  2004-10-10 19:33   ` PATCH Matt Porter
  0 siblings, 2 replies; 80+ messages in thread
From: Geert Uytterhoeven @ 2004-10-10 18:01 UTC (permalink / raw)
  To: Pete Popov; +Cc: linux-mips

On Sun, 10 Oct 2004, Pete Popov wrote:
> Ralf, or anyone else, any suggestions on how to get a patch like the one
> below accepted in 2.6? It's needed due to the 36 bit address of the
> pcmcia controller on the Au1x CPUs.

Perhaps you can ask the PPC people? Book E PPC has 36-bit I/O as well.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2004-10-10 17:17 Pete Popov
  2004-10-10 18:01 ` PATCH Geert Uytterhoeven
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2004-10-10 17:17 UTC (permalink / raw)
  To: linux-mips

Ralf, or anyone else, any suggestions on how to get a patch like the one
below accepted in 2.6? It's needed due to the 36 bit address of the
pcmcia controller on the Au1x CPUs.

diff -Naur --exclude=CVS linux-2.6-orig/include/pcmcia/cs_types.h linux-2.6-dev/include/pcmcia/cs_types.h
--- linux-2.6-orig/include/pcmcia/cs_types.h	2004-02-24 18:09:31.000000000 -0800
+++ linux-2.6-dev/include/pcmcia/cs_types.h	2004-09-25 19:57:11.000000000 -0700
@@ -36,8 +36,10 @@
 #include <sys/types.h>
 #endif
 
-#if defined(__arm__) || defined(__mips__)
-typedef u_int   ioaddr_t;
+#if defined(__arm__)
+typedef u_int ioaddr_t;
+#elif defined(__mips__)
+typedef phys_t ioaddr_t;
 #else
 typedef u_short	ioaddr_t;
 #endif
diff -Naur --exclude=CVS linux-2.6-orig/include/pcmcia/ss.h linux-2.6-dev/include/pcmcia/ss.h
--- linux-2.6-orig/include/pcmcia/ss.h	2004-09-22 23:20:17.000000000 -0700
+++ linux-2.6-dev/include/pcmcia/ss.h	2004-09-25 19:57:47.000000000 -0700
@@ -103,7 +103,7 @@
     u_char	map;
     u_char	flags;
     u_short	speed;
-    u_long	static_start;
+    ioaddr_t	static_start;
     u_int	card_start;
     struct resource *res;
 } pccard_mem_map;

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2004-10-10  7:17 Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-10  7:17 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips


36 bit I/O support patch, one more time -- looks like my email program
corrupted the patch, sorry.


Pete

Index: arch/mips/au1000/common/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/au1000/common/setup.c,v
retrieving revision 1.17
diff -u -r1.17 setup.c
--- arch/mips/au1000/common/setup.c	14 Sep 2004 06:38:46 -0000	1.17
+++ arch/mips/au1000/common/setup.c	19 Sep 2004 22:51:20 -0000
@@ -56,10 +56,6 @@
 extern void au1x_time_init(void);
 extern void (*board_timer_setup)(struct irqaction *irq);
 extern void au1x_timer_setup(struct irqaction *irq);
-#if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550))
-extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size);
-static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size);
-#endif
 extern void au1xxx_time_init(void);
 extern void au1xxx_timer_setup(struct irqaction *irq);
 extern void set_cpuspec(void);
@@ -147,9 +143,6 @@
 	_machine_power_off = au1000_power_off;
 	board_time_init = au1xxx_time_init;
 	board_timer_setup = au1xxx_timer_setup;
-#if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550))
-	fixup_bigphys_addr = au1500_fixup_bigphys_addr;
-#endif
 
 	/* IO/MEM resources. */
 	set_io_port_base(0);
@@ -200,7 +193,7 @@
 
 #if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550))
 /* This routine should be valid for all Au1500 based boards */
-static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
 {
 	u32 pci_start = (u32)Au1500_PCI_MEM_START;
 	u32 pci_end = (u32)Au1500_PCI_MEM_END;
Index: arch/mips/mm/Makefile
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/Makefile,v
retrieving revision 1.68
diff -u -r1.68 Makefile
--- arch/mips/mm/Makefile	20 Jun 2004 23:52:17 -0000	1.68
+++ arch/mips/mm/Makefile	19 Sep 2004 22:51:21 -0000
@@ -41,10 +41,11 @@
 obj-$(CONFIG_CPU_RM7000)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_RM9000)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_R10000)	+= tlbex32-r4k.o
-obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-r4k.o
+obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-mips32.o
 obj-$(CONFIG_CPU_MIPS64)	+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= tlbex32-r4k.o
 obj-$(CONFIG_CPU_TX39XX)	+= tlbex32-r3k.o
+obj-$(CONFIG_64BIT_PHYS_ADDR)	+= remap.o
 endif
 ifdef CONFIG_MIPS64
 obj-$(CONFIG_CPU_R4300)		+= tlb64-glue-r4k.o tlbex64-r4k.o
Index: arch/mips/mm/ioremap.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/ioremap.c,v
retrieving revision 1.19
diff -u -r1.19 ioremap.c
--- arch/mips/mm/ioremap.c	19 Apr 2004 16:36:35 -0000	1.19
+++ arch/mips/mm/ioremap.c	19 Sep 2004 22:51:21 -0000
@@ -97,6 +97,15 @@
 }
 
 /*
+ * Allow physical addresses to be fixed up to help 36 bit peripherals.
+ */
+phys_t __attribute__ ((weak))
+fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+/*
  * Generic mapping function (not visible outside):
  */
 
@@ -110,7 +119,7 @@
  * caller shouldn't need to know that small detail.
  */
 
-#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL))
+#define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))
 
 void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
 {
@@ -119,6 +128,8 @@
 	phys_t last_addr;
 	void * addr;
 
+	phys_addr = fixup_bigphys_addr(phys_addr, size);
+
 	/* Don't allow wraparound or zero size */
 	last_addr = phys_addr + size - 1;
 	if (!size || last_addr < phys_addr)
@@ -190,3 +201,4 @@
 
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(__iounmap);
+EXPORT_SYMBOL(fixup_bigphys_addr);
Index: arch/mips/mm/remap.c
===================================================================
RCS file: arch/mips/mm/remap.c
diff -N arch/mips/mm/remap.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/remap.c	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,115 @@
+/*
+ *  arch/mips/mm/remap.c
+ *
+ *  A copy of mm/memory.c, with mods for 64 bit physical I/O addresses on
+ *  32 bit native word platforms.
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ */
+
+
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/mman.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/rmap.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <linux/swapops.h>
+#include <linux/elf.h>
+
+
+/*
+ * maps a range of physical memory into the requested pages. the old
+ * mappings are removed. any references to nonexistent pages results
+ * in null mappings (currently treated as "copy-on-access")
+ */
+static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long end;
+	unsigned long pfn;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	pfn = phys_addr >> PAGE_SHIFT;
+	do {
+		BUG_ON(!pte_none(*pte));
+		if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
+ 			set_pte(pte, pfn_pte(pfn, prot));
+		address += PAGE_SIZE;
+		pfn++;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long base, end;
+
+	base = address & PGDIR_MASK;
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	do {
+		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
+		if (!pte)
+			return -ENOMEM;
+		remap_pte_range(pte, base + address, end - address, address + phys_addr, prot);
+		pte_unmap(pte);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+/*  Note: this is only safe if the mm semaphore is held when called. */
+int remap_page_range_high(struct vm_area_struct *vma, unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	int error = 0;
+	pgd_t * dir;
+	unsigned long beg = from;
+	unsigned long end = from + size;
+	struct mm_struct *mm = vma->vm_mm;
+
+	phys_addr -= from;
+	dir = pgd_offset(mm, from);
+	flush_cache_range(vma, beg, end);
+	if (from >= end)
+		BUG();
+
+	spin_lock(&mm->page_table_lock);
+	do {
+		pmd_t *pmd = pmd_alloc(mm, dir, from);
+		error = -ENOMEM;
+		if (!pmd)
+			break;
+		error = remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
+		if (error)
+			break;
+		from = (from + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (from && (from < end));
+	/*
+	 * Why flush? remap_pte_range has a BUG_ON for !pte_none()
+	 */
+	flush_tlb_range(vma, beg, end);
+	spin_unlock(&mm->page_table_lock);
+	return error;
+}
+
+EXPORT_SYMBOL(remap_page_range_high);
Index: arch/mips/mm/tlb-r4k.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/tlb-r4k.c,v
retrieving revision 1.38
diff -u -r1.38 tlb-r4k.c
--- arch/mips/mm/tlb-r4k.c	19 Mar 2004 04:07:59 -0000	1.38
+++ arch/mips/mm/tlb-r4k.c	19 Sep 2004 22:51:21 -0000
@@ -255,8 +255,14 @@
 	idx = read_c0_index();
 	ptep = pte_offset_map(pmdp, address);
 
-	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-	write_c0_entrylo1(pte_val(*ptep) >> 6);
+ #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ 	write_c0_entrylo0(ptep->pte_high);
+ 	ptep++;
+ 	write_c0_entrylo1(ptep->pte_high);
+#else
+  	write_c0_entrylo0(pte_val(*ptep++) >> 6);
+  	write_c0_entrylo1(pte_val(*ptep) >> 6);
+#endif
 	write_c0_entryhi(address | pid);
 	mtc0_tlbw_hazard();
 	if (idx < 0)
Index: arch/mips/mm/tlbex32-mips32.S
===================================================================
RCS file: arch/mips/mm/tlbex32-mips32.S
diff -N arch/mips/mm/tlbex32-mips32.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/tlbex32-mips32.S	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,325 @@
+/*
+ * TLB exception handling code for MIPS32 CPUs.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * Pete Popov, ppopov@pacbell.net
+ * Added 36 bit phys address support.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ */
+#include <linux/init.h>
+#include <asm/asm.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable-bits.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define TLB_OPTIMIZE /* If you are paranoid, disable this. */
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+
+/* We really only support 36 bit physical addresses on MIPS32 */
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        4 /* pte_high contains pre-shifted, ready to go entry */
+#define PTE_SIZE        8
+#define PTEP_INDX_MSK	0xff0
+#define PTE_INDX_MSK	0xff8
+#define PTE_INDX_SHIFT 9
+#define CONVERT_PTE(pte)
+#define PTE_MAKEWRITE_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, (_PAGE_VALID | _PAGE_DIRTY); \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#define PTE_MAKEVALID_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, pte, _PAGE_VALID; \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#else
+
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        0
+#define PTE_SIZE	4
+#define PTEP_INDX_MSK	0xff8
+#define PTE_INDX_MSK	0xffc
+#define PTE_INDX_SHIFT	10
+#define CONVERT_PTE(pte) srl pte, pte, 6
+#define PTE_MAKEWRITE_HIGH(pte, ptr)
+#define PTE_MAKEVALID_HIGH(pte, ptr)
+
+#endif  /* CONFIG_64BIT_PHYS_ADDR */
+
+	__INIT
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define GET_PTE_OFF(reg)
+#else
+#define GET_PTE_OFF(reg)	srl	reg, reg, 1
+#endif
+
+/*	
+ * These handlers much be written in a relocatable manner
+ * because based upon the cpu type an arbitrary one of the
+ * following pieces of code will be copied to the KSEG0
+ * vector location.
+ */
+	/* TLB refill, EXL == 0, MIPS32 version */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4000)
+	.set	mips3
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_CONTEXT
+	la	k0, pgd_current
+	srl	k1, 23
+	sll	k1, 2				# log2(sizeof(pgd_t)
+	addu	k1, k0, k1
+	lw	k1, (k1)
+#else 
+	lw	k1, pgd_current			# get pgd pointer
+#endif	
+	nop
+	mfc0	k0, CP0_BADVADDR		# Get faulting address
+	srl	k0, k0, _PGDIR_SHIFT		# get pgd only bits
+
+	sll	k0, k0, 2
+	addu	k1, k1, k0			# add in pgd offset
+	mfc0	k0, CP0_CONTEXT			# get context reg
+	lw	k1, (k1)
+	GET_PTE_OFF(k0)				# get pte offset
+	and	k0, k0, PTEP_INDX_MSK
+	addu	k1, k1, k0			# add in offset
+
+	PTE_L	k0, PTE_HALF(k1)		# get even pte
+	CONVERT_PTE(k0)
+	P_MTC0	k0, CP0_ENTRYLO0		# load it
+	PTE_L	k1, (PTE_HALF+PTE_SIZE)(k1)	# get odd pte
+	CONVERT_PTE(k1)
+	P_MTC0	k1, CP0_ENTRYLO1		# load it
+	b	1f
+	tlbwr					# write random tlb entry
+1:
+	nop
+	eret					# return from trap
+	END(except_vec0_r4000)
+
+/*
+ * These are here to avoid putting ifdefs in tlb-r4k.c
+ */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_nevada)
+	.set	mips3
+	PANIC("Nevada Exception Vec 0 called")
+	END(except_vec0_nevada)
+
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4600)
+	.set	mips3
+	PANIC("R4600 Exception Vec 0 called")
+	END(except_vec0_r4600)
+
+	__FINIT
+
+/*
+ * ABUSE of CPP macros 101.
+ *
+ * After this macro runs, the pte faulted on is
+ * in register PTE, a ptr into the table in which
+ * the pte belongs is in PTR.
+ */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, pgd_current;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);          
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, pgd_current;
+#endif
+
+#define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
+	mfc0	pte, CP0_BADVADDR; \
+	srl	pte, pte, _PGDIR_SHIFT; \
+	sll	pte, pte, 2; \
+	addu	ptr, ptr, pte; \
+	mfc0	pte, CP0_BADVADDR; \
+	lw	ptr, (ptr); \
+	srl	pte, pte, PTE_INDX_SHIFT; \
+	and	pte, pte, PTE_INDX_MSK; \
+	addu	ptr, ptr, pte; \
+	PTE_L	pte, (ptr);
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr, tmp) \
+	ori	ptr, ptr, PTE_SIZE; \
+	xori	ptr, ptr, PTE_SIZE; \
+	PTE_L	tmp, (PTE_HALF+PTE_SIZE)(ptr); \
+	CONVERT_PTE(tmp); \
+	P_MTC0	tmp, CP0_ENTRYLO1; \
+	PTE_L	ptr, PTE_HALF(ptr); \
+	CONVERT_PTE(ptr); \
+	P_MTC0	ptr, CP0_ENTRYLO0;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	STI; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_exception; \
+	 nop; \
+	.set	noat;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	PTE_S	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	PTE_S	pte, (ptr);
+
+	.set	noreorder
+
+#define R5K_HAZARD nop
+
+	.align	5
+	NESTED(handle_tlbl, PT_SIZE, sp)
+	.set	noat
+invalid_tlbl:
+#ifdef TLB_OPTIMIZE
+	/* Test present bit in entry. */
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp
+	PTE_PRESENT(k0, k1, nopage_tlbl)
+	PTE_MAKEVALID_HIGH(k0, k1)
+	PTE_MAKEVALID(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3	
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbl:
+	DO_FAULT(0)
+	END(handle_tlbl)
+
+	.align	5
+	NESTED(handle_tlbs, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+        li      k0,0
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp				# find faulting entry
+	PTE_WRITABLE(k0, k1, nopage_tlbs)
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbs:
+	DO_FAULT(1)
+	END(handle_tlbs)
+
+	.align	5
+	NESTED(handle_mod, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp					# find faulting entry
+	andi	k0, k0, _PAGE_WRITE
+	beqz	k0, nowrite_mod
+	PTE_L	k0, (k1)
+
+	/* Present and writable bits set, set accessed and dirty bits. */
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	/* Now reload the entry into the tlb. */
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nowrite_mod:
+	DO_FAULT(1)
+	END(handle_mod)
+
Index: include/asm-mips/addrspace.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/addrspace.h,v
retrieving revision 1.13
diff -u -r1.13 addrspace.h
--- include/asm-mips/addrspace.h	30 Nov 2003 01:52:25 -0000	1.13
+++ include/asm-mips/addrspace.h	19 Sep 2004 22:51:28 -0000
@@ -80,7 +80,11 @@
 #define XKSSEG			0x4000000000000000
 #define XKPHYS			0x8000000000000000
 #define XKSEG			0xc000000000000000
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#define CKSEG0			0x80000000
+#else
 #define CKSEG0			0xffffffff80000000
+#endif
 #define CKSEG1			0xffffffffa0000000
 #define CKSSEG			0xffffffffc0000000
 #define CKSEG3			0xffffffffe0000000
Index: include/asm-mips/io.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/io.h,v
retrieving revision 1.72
diff -u -r1.72 io.h
--- include/asm-mips/io.h	19 Aug 2004 15:27:41 -0000	1.72
+++ include/asm-mips/io.h	19 Sep 2004 22:51:29 -0000
@@ -171,7 +171,7 @@
 extern void * __ioremap(phys_t offset, phys_t size, unsigned long flags);
 extern void __iounmap(void *addr);
 
-static inline void * __ioremap_mode(unsigned long offset, unsigned long size,
+static inline void * __ioremap_mode(phys_t offset, unsigned long size,
 	unsigned long flags)
 {
 	if (cpu_has_64bit_addresses) {
Index: include/asm-mips/page.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/page.h,v
retrieving revision 1.44
diff -u -r1.44 page.h
--- include/asm-mips/page.h	20 Aug 2004 12:02:18 -0000	1.44
+++ include/asm-mips/page.h	19 Sep 2004 22:51:29 -0000
@@ -32,7 +32,7 @@
 #ifdef CONFIG_PAGE_SIZE_64KB
 #define PAGE_SHIFT	16
 #endif
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_SIZE	(1L << PAGE_SHIFT)
 #define PAGE_MASK	(~(PAGE_SIZE-1))
 
 #ifdef __KERNEL__
@@ -75,15 +75,22 @@
  * These are used to make use of C type-checking..
  */
 #ifdef CONFIG_64BIT_PHYS_ADDR
-typedef struct { unsigned long long pte; } pte_t;
+  #ifdef CONFIG_CPU_MIPS32
+    typedef struct { unsigned long pte_low, pte_high; } pte_t;
+    #define pte_val(x)    ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+  #else
+     typedef struct { unsigned long long pte; } pte_t;
+     #define pte_val(x)	((x).pte)
+  #endif
 #else
 typedef struct { unsigned long pte; } pte_t;
+#define pte_val(x)	((x).pte)
 #endif
+
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
-#define pte_val(x)	((x).pte)
 #define pmd_val(x)	((x).pmd)
 #define pgd_val(x)	((x).pgd)
 #define pgprot_val(x)	((x).pgprot)
Index: include/asm-mips/pgtable-32.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-32.h,v
retrieving revision 1.11
diff -u -r1.11 pgtable-32.h
--- include/asm-mips/pgtable-32.h	26 Jun 2004 15:15:24 -0000	1.11
+++ include/asm-mips/pgtable-32.h	19 Sep 2004 22:51:29 -0000
@@ -130,8 +130,21 @@
 static inline int pgd_present(pgd_t pgd)	{ return 1; }
 static inline void pgd_clear(pgd_t *pgdp)	{ }
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pte_pfn(x)		((unsigned long)((x).pte_high >> 6))
+static inline pte_t
+pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+	pte_t pte;
+	pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f);
+	pte.pte_low = pgprot_val(prot);
+	return pte;
+}
+
+#else
 
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
 
 #ifdef CONFIG_CPU_VR41XX
 #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
@@ -140,6 +153,7 @@
 #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 #endif
+#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32) */
 
 #define __pgd_offset(address)	pgd_index(address)
 #define __pmd_offset(address)	(((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
@@ -207,11 +221,19 @@
  */
 #define PTE_FILE_MAX_BITS	27
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+	/* fixme */
+#define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 0x3f))
+#define pgoff_to_pte(off) \
+ 	((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)})
+  
+#else
 #define pte_to_pgoff(_pte) \
 	((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))
 
 #define pgoff_to_pte(off) \
 	((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#endif
 
 #endif
 
Index: include/asm-mips/pgtable-bits.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-bits.h,v
retrieving revision 1.9
diff -u -r1.9 pgtable-bits.h
--- include/asm-mips/pgtable-bits.h	24 Jun 2004 20:31:11 -0000	1.9
+++ include/asm-mips/pgtable-bits.h	19 Sep 2004 22:51:29 -0000
@@ -33,6 +33,31 @@
  * unpredictable things.  The code (when it is written) to deal with
  * this problem will be in the update_mmu_cache() code for the r4k.
  */
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+
+#define _PAGE_PRESENT               (1<<6)  /* implemented in software */
+#define _PAGE_READ                  (1<<7)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<8)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<9)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<10) /* implemented in software */
+#define _PAGE_FILE                  (1<<10)  /* set:pagecache unset:swap */
+
+#define _PAGE_R4KBUG                (1<<0)  /* workaround for r4k bug  */
+#define _PAGE_GLOBAL                (1<<0)
+#define _PAGE_VALID                 (1<<1)
+#define _PAGE_SILENT_READ           (1<<1)  /* synonym                 */
+#define _PAGE_DIRTY                 (1<<2)  /* The MIPS dirty bit      */
+#define _PAGE_SILENT_WRITE          (1<<2)
+#define _CACHE_MASK                 (7<<3)
+
+/* MIPS32 defines only values 2 and 3. The rest are implementation
+ * dependent.
+ */
+#define _CACHE_UNCACHED             (2<<3)  
+#define _CACHE_CACHABLE_NONCOHERENT (3<<3) 
+
+#else
+
 #define _PAGE_PRESENT               (1<<0)  /* implemented in software */
 #define _PAGE_READ                  (1<<1)  /* implemented in software */
 #define _PAGE_WRITE                 (1<<2)  /* implemented in software */
@@ -97,6 +122,7 @@
 
 #endif
 #endif
+#endif /* defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR) */
 
 #define __READABLE	(_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
 #define __WRITEABLE	(_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
@@ -113,6 +139,10 @@
 #define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_COW
 #endif
 
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+#define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 3)
+#else
 #define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 9)
+#endif
 
 #endif /* _ASM_PGTABLE_BITS_H */
Index: include/asm-mips/pgtable.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable.h,v
retrieving revision 1.97
diff -u -r1.97 pgtable.h
--- include/asm-mips/pgtable.h	19 Jun 2004 01:39:24 -0000	1.97
+++ include/asm-mips/pgtable.h	19 Sep 2004 22:51:29 -0000
@@ -80,6 +80,34 @@
 #define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+	ptep->pte_high = pte.pte_high;
+	smp_wmb();
+	ptep->pte_low = pte.pte_low;
+	//printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
+
+	if (pte_val(pte) & _PAGE_GLOBAL) {
+		pte_t *buddy = ptep_buddy(ptep);
+		/*
+		 * Make sure the buddy is global too (if it's !none,
+		 * it better already be global)
+		 */
+		if (pte_none(*buddy))
+			buddy->pte_low |= _PAGE_GLOBAL;
+	}
+}
+
+static inline void pte_clear(pte_t *ptep)
+{
+	/* Preserve global status for the pair */
+	if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
+		set_pte(ptep, __pte(_PAGE_GLOBAL));
+	else
+		set_pte(ptep, __pte(0));
+}
+#else
 /*
  * Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
@@ -111,6 +139,7 @@
 #endif
 		set_pte(ptep, __pte(0));
 }
+#endif
 
 /*
  * (pmds are folded into pgds so this doesn't get actually called,
@@ -130,6 +159,79 @@
  * Undefined behaviour if not..
  */
 static inline int pte_user(pte_t pte)	{ BUG(); return 0; }
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline int pte_read(pte_t pte)	{ return (pte).pte_low & _PAGE_READ; }
+static inline int pte_write(pte_t pte)	{ return (pte).pte_low & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte)	{ return (pte).pte_low & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte)	{ return (pte).pte_low & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)	{ return (pte).pte_low & _PAGE_FILE; }
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_WRITE;
+	if ((pte).pte_low & _PAGE_MODIFIED) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_READ;
+	if ((pte).pte_low & _PAGE_ACCESSED) {
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_MODIFIED;
+	if ((pte).pte_low & _PAGE_WRITE) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_ACCESSED;
+	if ((pte).pte_low & _PAGE_READ)
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	return pte;
+}
+#else
 static inline int pte_read(pte_t pte)	{ return pte_val(pte) & _PAGE_READ; }
 static inline int pte_write(pte_t pte)	{ return pte_val(pte) & _PAGE_WRITE; }
 static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_MODIFIED; }
@@ -191,6 +293,7 @@
 		pte_val(pte) |= _PAGE_SILENT_READ;
 	return pte;
 }
+#endif
 
 /*
  * Macro to make mark a page protection value as "uncacheable".  Note
@@ -215,10 +318,20 @@
  */
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
 
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte.pte_low &= _PAGE_CHG_MASK;
+	pte.pte_low |= pgprot_val(newprot);
+	pte.pte_high |= pgprot_val(newprot) & 0x3f;
+	return pte;
+}
+#else
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
 	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
 }
+#endif
 

 extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
@@ -245,7 +358,27 @@
  */
 #define HAVE_ARCH_UNMAPPED_AREA
 
+#ifdef CONFIG_64BIT_PHYS_ADDR
+extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
+
+extern int remap_page_range_high(struct vm_area_struct *vma,
+		unsigned long from,
+		phys_t phys_addr,
+		unsigned long size,
+		pgprot_t prot);
+
+static inline int io_remap_page_range(struct vm_area_struct *vma,
+		unsigned long from,
+		unsigned long phys_addr,
+		unsigned long size,
+		pgprot_t prot)
+{
+	phys_t phys_addr_high = fixup_bigphys_addr(phys_addr, size);
+	return remap_page_range_high(vma, from, phys_addr_high, size, prot);
+}
+#else
 #define io_remap_page_range remap_page_range
+#endif
 
 /*
  * No page table caches to initialise

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2004-10-10  5:31 Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-10-10  5:31 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Ralf,

Here is the 2.6 36 bit I/O support patch. We beat up on it quite a bit 
and it seems solid on the Au1x (Db1500 board).

Pete

Index: arch/mips/au1000/common/setup.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/au1000/common/setup.c,v
retrieving revision 1.17
diff -u -r1.17 setup.c
--- arch/mips/au1000/common/setup.c	14 Sep 2004 06:38:46 -0000	1.17
+++ arch/mips/au1000/common/setup.c	19 Sep 2004 22:51:20 -0000
@@ -56,10 +56,6 @@
  extern void au1x_time_init(void);
  extern void (*board_timer_setup)(struct irqaction *irq);
  extern void au1x_timer_setup(struct irqaction *irq);
-#if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || 
defined(CONFIG_SOC_AU1550))
-extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size);
-static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size);
-#endif
  extern void au1xxx_time_init(void);
  extern void au1xxx_timer_setup(struct irqaction *irq);
  extern void set_cpuspec(void);
@@ -147,9 +143,6 @@
  	_machine_power_off = au1000_power_off;
  	board_time_init = au1xxx_time_init;
  	board_timer_setup = au1xxx_timer_setup;
-#if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || 
defined(CONFIG_SOC_AU1550))
-	fixup_bigphys_addr = au1500_fixup_bigphys_addr;
-#endif

  	/* IO/MEM resources. */
  	set_io_port_base(0);
@@ -200,7 +193,7 @@

  #if defined(CONFIG_64BIT_PHYS_ADDR) && (defined(CONFIG_SOC_AU1500) || 
defined(CONFIG_SOC_AU1550))
  /* This routine should be valid for all Au1500 based boards */
-static phys_t au1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
  {
  	u32 pci_start = (u32)Au1500_PCI_MEM_START;
  	u32 pci_end = (u32)Au1500_PCI_MEM_END;
Index: arch/mips/mm/Makefile
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/Makefile,v
retrieving revision 1.68
diff -u -r1.68 Makefile
--- arch/mips/mm/Makefile	20 Jun 2004 23:52:17 -0000	1.68
+++ arch/mips/mm/Makefile	19 Sep 2004 22:51:21 -0000
@@ -41,10 +41,11 @@
  obj-$(CONFIG_CPU_RM7000)	+= tlbex32-r4k.o
  obj-$(CONFIG_CPU_RM9000)	+= tlbex32-r4k.o
  obj-$(CONFIG_CPU_R10000)	+= tlbex32-r4k.o
-obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-r4k.o
+obj-$(CONFIG_CPU_MIPS32)	+= tlbex32-mips32.o
  obj-$(CONFIG_CPU_MIPS64)	+= tlbex32-r4k.o
  obj-$(CONFIG_CPU_SB1)		+= tlbex32-r4k.o
  obj-$(CONFIG_CPU_TX39XX)	+= tlbex32-r3k.o
+obj-$(CONFIG_64BIT_PHYS_ADDR)	+= remap.o
  endif
  ifdef CONFIG_MIPS64
  obj-$(CONFIG_CPU_R4300)		+= tlb64-glue-r4k.o tlbex64-r4k.o
Index: arch/mips/mm/ioremap.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/ioremap.c,v
retrieving revision 1.19
diff -u -r1.19 ioremap.c
--- arch/mips/mm/ioremap.c	19 Apr 2004 16:36:35 -0000	1.19
+++ arch/mips/mm/ioremap.c	19 Sep 2004 22:51:21 -0000
@@ -97,6 +97,15 @@
  }

  /*
+ * Allow physical addresses to be fixed up to help 36 bit peripherals.
+ */
+phys_t __attribute__ ((weak))
+fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+/*
   * Generic mapping function (not visible outside):
   */

@@ -110,7 +119,7 @@
   * caller shouldn't need to know that small detail.
   */

-#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL))
+#define IS_LOW512(addr) (!((phys_t)(addr) & (phys_t) ~0x1fffffffULL))

  void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
  {
@@ -119,6 +128,8 @@
  	phys_t last_addr;
  	void * addr;

+	phys_addr = fixup_bigphys_addr(phys_addr, size);
+
  	/* Don't allow wraparound or zero size */
  	last_addr = phys_addr + size - 1;
  	if (!size || last_addr < phys_addr)
@@ -190,3 +201,4 @@

  EXPORT_SYMBOL(__ioremap);
  EXPORT_SYMBOL(__iounmap);
+EXPORT_SYMBOL(fixup_bigphys_addr);
Index: arch/mips/mm/remap.c
===================================================================
RCS file: arch/mips/mm/remap.c
diff -N arch/mips/mm/remap.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/remap.c	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,115 @@
+/*
+ *  arch/mips/mm/remap.c
+ *
+ *  A copy of mm/memory.c, with mods for 64 bit physical I/O addresses on
+ *  32 bit native word platforms.
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ */
+
+
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/mman.h>
+#include <linux/swap.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/rmap.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/pgalloc.h>
+#include <asm/uaccess.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/pgtable.h>
+
+#include <linux/swapops.h>
+#include <linux/elf.h>
+
+
+/*
+ * maps a range of physical memory into the requested pages. the old
+ * mappings are removed. any references to nonexistent pages results
+ * in null mappings (currently treated as "copy-on-access")
+ */
+static inline void remap_pte_range(pte_t * pte, unsigned long address, 
unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long end;
+	unsigned long pfn;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	pfn = phys_addr >> PAGE_SHIFT;
+	do {
+		BUG_ON(!pte_none(*pte));
+		if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
+ 			set_pte(pte, pfn_pte(pfn, prot));
+		address += PAGE_SIZE;
+		pfn++;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, 
unsigned long address, unsigned long size,
+	phys_t phys_addr, pgprot_t prot)
+{
+	unsigned long base, end;
+
+	base = address & PGDIR_MASK;
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	do {
+		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
+		if (!pte)
+			return -ENOMEM;
+		remap_pte_range(pte, base + address, end - address, address + 
phys_addr, prot);
+		pte_unmap(pte);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+/*  Note: this is only safe if the mm semaphore is held when called. */
+int remap_page_range_high(struct vm_area_struct *vma, unsigned long 
from, phys_t phys_addr, unsigned long size, pgprot_t prot)
+{
+	int error = 0;
+	pgd_t * dir;
+	unsigned long beg = from;
+	unsigned long end = from + size;
+	struct mm_struct *mm = vma->vm_mm;
+
+	phys_addr -= from;
+	dir = pgd_offset(mm, from);
+	flush_cache_range(vma, beg, end);
+	if (from >= end)
+		BUG();
+
+	spin_lock(&mm->page_table_lock);
+	do {
+		pmd_t *pmd = pmd_alloc(mm, dir, from);
+		error = -ENOMEM;
+		if (!pmd)
+			break;
+		error = remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, 
prot);
+		if (error)
+			break;
+		from = (from + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (from && (from < end));
+	/*
+	 * Why flush? remap_pte_range has a BUG_ON for !pte_none()
+	 */
+	flush_tlb_range(vma, beg, end);
+	spin_unlock(&mm->page_table_lock);
+	return error;
+}
+
+EXPORT_SYMBOL(remap_page_range_high);
Index: arch/mips/mm/tlb-r4k.c
===================================================================
RCS file: /home/cvs/linux/arch/mips/mm/tlb-r4k.c,v
retrieving revision 1.38
diff -u -r1.38 tlb-r4k.c
--- arch/mips/mm/tlb-r4k.c	19 Mar 2004 04:07:59 -0000	1.38
+++ arch/mips/mm/tlb-r4k.c	19 Sep 2004 22:51:21 -0000
@@ -255,8 +255,14 @@
  	idx = read_c0_index();
  	ptep = pte_offset_map(pmdp, address);

-	write_c0_entrylo0(pte_val(*ptep++) >> 6);
-	write_c0_entrylo1(pte_val(*ptep) >> 6);
+ #if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+ 	write_c0_entrylo0(ptep->pte_high);
+ 	ptep++;
+ 	write_c0_entrylo1(ptep->pte_high);
+#else
+  	write_c0_entrylo0(pte_val(*ptep++) >> 6);
+  	write_c0_entrylo1(pte_val(*ptep) >> 6);
+#endif
  	write_c0_entryhi(address | pid);
  	mtc0_tlbw_hazard();
  	if (idx < 0)
Index: arch/mips/mm/tlbex32-mips32.S
===================================================================
RCS file: arch/mips/mm/tlbex32-mips32.S
diff -N arch/mips/mm/tlbex32-mips32.S
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ arch/mips/mm/tlbex32-mips32.S	19 Sep 2004 22:51:21 -0000
@@ -0,0 +1,325 @@
+/*
+ * TLB exception handling code for MIPS32 CPUs.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * Pete Popov, ppopov@pacbell.net
+ * Added 36 bit phys address support.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ */
+#include <linux/init.h>
+#include <asm/asm.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable-bits.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define TLB_OPTIMIZE /* If you are paranoid, disable this. */
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+
+/* We really only support 36 bit physical addresses on MIPS32 */
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        4 /* pte_high contains pre-shifted, ready to go 
entry */
+#define PTE_SIZE        8
+#define PTEP_INDX_MSK	0xff0
+#define PTE_INDX_MSK	0xff8
+#define PTE_INDX_SHIFT 9
+#define CONVERT_PTE(pte)
+#define PTE_MAKEWRITE_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, (_PAGE_VALID | _PAGE_DIRTY); \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#define PTE_MAKEVALID_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, pte, _PAGE_VALID; \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#else
+
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        0
+#define PTE_SIZE	4
+#define PTEP_INDX_MSK	0xff8
+#define PTE_INDX_MSK	0xffc
+#define PTE_INDX_SHIFT	10
+#define CONVERT_PTE(pte) srl pte, pte, 6
+#define PTE_MAKEWRITE_HIGH(pte, ptr)
+#define PTE_MAKEVALID_HIGH(pte, ptr)
+
+#endif  /* CONFIG_64BIT_PHYS_ADDR */
+
+	__INIT
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define GET_PTE_OFF(reg)
+#else
+#define GET_PTE_OFF(reg)	srl	reg, reg, 1
+#endif
+
+/*	
+ * These handlers much be written in a relocatable manner
+ * because based upon the cpu type an arbitrary one of the
+ * following pieces of code will be copied to the KSEG0
+ * vector location.
+ */
+	/* TLB refill, EXL == 0, MIPS32 version */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4000)
+	.set	mips3
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_CONTEXT
+	la	k0, pgd_current
+	srl	k1, 23
+	sll	k1, 2				# log2(sizeof(pgd_t)
+	addu	k1, k0, k1
+	lw	k1, (k1)
+#else
+	lw	k1, pgd_current			# get pgd pointer
+#endif	
+	nop
+	mfc0	k0, CP0_BADVADDR		# Get faulting address
+	srl	k0, k0, _PGDIR_SHIFT		# get pgd only bits
+
+	sll	k0, k0, 2
+	addu	k1, k1, k0			# add in pgd offset
+	mfc0	k0, CP0_CONTEXT			# get context reg
+	lw	k1, (k1)
+	GET_PTE_OFF(k0)				# get pte offset
+	and	k0, k0, PTEP_INDX_MSK
+	addu	k1, k1, k0			# add in offset
+
+	PTE_L	k0, PTE_HALF(k1)		# get even pte
+	CONVERT_PTE(k0)
+	P_MTC0	k0, CP0_ENTRYLO0		# load it
+	PTE_L	k1, (PTE_HALF+PTE_SIZE)(k1)	# get odd pte
+	CONVERT_PTE(k1)
+	P_MTC0	k1, CP0_ENTRYLO1		# load it
+	b	1f
+	tlbwr					# write random tlb entry
+1:
+	nop
+	eret					# return from trap
+	END(except_vec0_r4000)
+
+/*
+ * These are here to avoid putting ifdefs in tlb-r4k.c
+ */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_nevada)
+	.set	mips3
+	PANIC("Nevada Exception Vec 0 called")
+	END(except_vec0_nevada)
+
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4600)
+	.set	mips3
+	PANIC("R4600 Exception Vec 0 called")
+	END(except_vec0_r4600)
+
+	__FINIT
+
+/*
+ * ABUSE of CPP macros 101.
+ *
+ * After this macro runs, the pte faulted on is
+ * in register PTE, a ptr into the table in which
+ * the pte belongs is in PTR.
+ */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, pgd_current;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, pgd_current;
+#endif
+
+#define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
+	mfc0	pte, CP0_BADVADDR; \
+	srl	pte, pte, _PGDIR_SHIFT; \
+	sll	pte, pte, 2; \
+	addu	ptr, ptr, pte; \
+	mfc0	pte, CP0_BADVADDR; \
+	lw	ptr, (ptr); \
+	srl	pte, pte, PTE_INDX_SHIFT; \
+	and	pte, pte, PTE_INDX_MSK; \
+	addu	ptr, ptr, pte; \
+	PTE_L	pte, (ptr);
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr, tmp) \
+	ori	ptr, ptr, PTE_SIZE; \
+	xori	ptr, ptr, PTE_SIZE; \
+	PTE_L	tmp, (PTE_HALF+PTE_SIZE)(ptr); \
+	CONVERT_PTE(tmp); \
+	P_MTC0	tmp, CP0_ENTRYLO1; \
+	PTE_L	ptr, PTE_HALF(ptr); \
+	CONVERT_PTE(ptr); \
+	P_MTC0	ptr, CP0_ENTRYLO0;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	STI; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_exception; \
+	 nop; \
+	.set	noat;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	PTE_S	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	PTE_S	pte, (ptr);
+
+	.set	noreorder
+
+#define R5K_HAZARD nop
+
+	.align	5
+	NESTED(handle_tlbl, PT_SIZE, sp)
+	.set	noat
+invalid_tlbl:
+#ifdef TLB_OPTIMIZE
+	/* Test present bit in entry. */
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp
+	PTE_PRESENT(k0, k1, nopage_tlbl)
+	PTE_MAKEVALID_HIGH(k0, k1)
+	PTE_MAKEVALID(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3	
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbl:
+	DO_FAULT(0)
+	END(handle_tlbl)
+
+	.align	5
+	NESTED(handle_tlbs, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+        li      k0,0
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp				# find faulting entry
+	PTE_WRITABLE(k0, k1, nopage_tlbs)
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbs:
+	DO_FAULT(1)
+	END(handle_tlbs)
+
+	.align	5
+	NESTED(handle_mod, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp					# find faulting entry
+	andi	k0, k0, _PAGE_WRITE
+	beqz	k0, nowrite_mod
+	PTE_L	k0, (k1)
+
+	/* Present and writable bits set, set accessed and dirty bits. */
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	/* Now reload the entry into the tlb. */
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nowrite_mod:
+	DO_FAULT(1)
+	END(handle_mod)
+
Index: include/asm-mips/addrspace.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/addrspace.h,v
retrieving revision 1.13
diff -u -r1.13 addrspace.h
--- include/asm-mips/addrspace.h	30 Nov 2003 01:52:25 -0000	1.13
+++ include/asm-mips/addrspace.h	19 Sep 2004 22:51:28 -0000
@@ -80,7 +80,11 @@
  #define XKSSEG			0x4000000000000000
  #define XKPHYS			0x8000000000000000
  #define XKSEG			0xc000000000000000
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#define CKSEG0			0x80000000
+#else
  #define CKSEG0			0xffffffff80000000
+#endif
  #define CKSEG1			0xffffffffa0000000
  #define CKSSEG			0xffffffffc0000000
  #define CKSEG3			0xffffffffe0000000
Index: include/asm-mips/io.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/io.h,v
retrieving revision 1.72
diff -u -r1.72 io.h
--- include/asm-mips/io.h	19 Aug 2004 15:27:41 -0000	1.72
+++ include/asm-mips/io.h	19 Sep 2004 22:51:29 -0000
@@ -171,7 +171,7 @@
  extern void * __ioremap(phys_t offset, phys_t size, unsigned long flags);
  extern void __iounmap(void *addr);

-static inline void * __ioremap_mode(unsigned long offset, unsigned long 
size,
+static inline void * __ioremap_mode(phys_t offset, unsigned long size,
  	unsigned long flags)
  {
  	if (cpu_has_64bit_addresses) {
Index: include/asm-mips/page.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/page.h,v
retrieving revision 1.44
diff -u -r1.44 page.h
--- include/asm-mips/page.h	20 Aug 2004 12:02:18 -0000	1.44
+++ include/asm-mips/page.h	19 Sep 2004 22:51:29 -0000
@@ -32,7 +32,7 @@
  #ifdef CONFIG_PAGE_SIZE_64KB
  #define PAGE_SHIFT	16
  #endif
-#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_SIZE	(1L << PAGE_SHIFT)
  #define PAGE_MASK	(~(PAGE_SIZE-1))

  #ifdef __KERNEL__
@@ -75,15 +75,22 @@
   * These are used to make use of C type-checking..
   */
  #ifdef CONFIG_64BIT_PHYS_ADDR
-typedef struct { unsigned long long pte; } pte_t;
+  #ifdef CONFIG_CPU_MIPS32
+    typedef struct { unsigned long pte_low, pte_high; } pte_t;
+    #define pte_val(x)    ((x).pte_low | ((unsigned long 
long)(x).pte_high << 32))
+  #else
+     typedef struct { unsigned long long pte; } pte_t;
+     #define pte_val(x)	((x).pte)
+  #endif
  #else
  typedef struct { unsigned long pte; } pte_t;
+#define pte_val(x)	((x).pte)
  #endif
+
  typedef struct { unsigned long pmd; } pmd_t;
  typedef struct { unsigned long pgd; } pgd_t;
  typedef struct { unsigned long pgprot; } pgprot_t;

-#define pte_val(x)	((x).pte)
  #define pmd_val(x)	((x).pmd)
  #define pgd_val(x)	((x).pgd)
  #define pgprot_val(x)	((x).pgprot)
Index: include/asm-mips/pgtable-32.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-32.h,v
retrieving revision 1.11
diff -u -r1.11 pgtable-32.h
--- include/asm-mips/pgtable-32.h	26 Jun 2004 15:15:24 -0000	1.11
+++ include/asm-mips/pgtable-32.h	19 Sep 2004 22:51:29 -0000
@@ -130,8 +130,21 @@
  static inline int pgd_present(pgd_t pgd)	{ return 1; }
  static inline void pgd_clear(pgd_t *pgdp)	{ }

+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
  #define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pte_pfn(x)		((unsigned long)((x).pte_high >> 6))
+static inline pte_t
+pfn_pte(unsigned long pfn, pgprot_t prot)
+{
+	pte_t pte;
+	pte.pte_high = (pfn << 6) | (pgprot_val(prot) & 0x3f);
+	pte.pte_low = pgprot_val(prot);
+	return pte;
+}
+
+#else

+#define pte_page(x)		pfn_to_page(pte_pfn(x))

  #ifdef CONFIG_CPU_VR41XX
  #define pte_pfn(x)		((unsigned long)((x).pte >> (PAGE_SHIFT + 2)))
@@ -140,6 +153,7 @@
  #define pte_pfn(x)		((unsigned long)((x).pte >> PAGE_SHIFT))
  #define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
  #endif
+#endif /* defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32) */

  #define __pgd_offset(address)	pgd_index(address)
  #define __pmd_offset(address)	(((address) >> PMD_SHIFT) & 
(PTRS_PER_PMD-1))
@@ -207,11 +221,19 @@
   */
  #define PTE_FILE_MAX_BITS	27

+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+	/* fixme */
+#define pte_to_pgoff(_pte) (((_pte).pte_high >> 6) + ((_pte).pte_high & 
0x3f))
+#define pgoff_to_pte(off) \
+ 	((pte_t){(((off) & 0x3f) + ((off) << 6) + _PAGE_FILE)})
+
+#else
  #define pte_to_pgoff(_pte) \
  	((((_pte).pte >> 3) & 0x1f ) + (((_pte).pte >> 9) << 6 ))

  #define pgoff_to_pte(off) \
  	((pte_t) { (((off) & 0x1f) << 3) + (((off) >> 6) << 9) + _PAGE_FILE })
+#endif

  #endif

Index: include/asm-mips/pgtable-bits.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable-bits.h,v
retrieving revision 1.9
diff -u -r1.9 pgtable-bits.h
--- include/asm-mips/pgtable-bits.h	24 Jun 2004 20:31:11 -0000	1.9
+++ include/asm-mips/pgtable-bits.h	19 Sep 2004 22:51:29 -0000
@@ -33,6 +33,31 @@
   * unpredictable things.  The code (when it is written) to deal with
   * this problem will be in the update_mmu_cache() code for the r4k.
   */
+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+
+#define _PAGE_PRESENT               (1<<6)  /* implemented in software */
+#define _PAGE_READ                  (1<<7)  /* implemented in software */
+#define _PAGE_WRITE                 (1<<8)  /* implemented in software */
+#define _PAGE_ACCESSED              (1<<9)  /* implemented in software */
+#define _PAGE_MODIFIED              (1<<10) /* implemented in software */
+#define _PAGE_FILE                  (1<<10)  /* set:pagecache unset:swap */
+
+#define _PAGE_R4KBUG                (1<<0)  /* workaround for r4k bug  */
+#define _PAGE_GLOBAL                (1<<0)
+#define _PAGE_VALID                 (1<<1)
+#define _PAGE_SILENT_READ           (1<<1)  /* synonym                 */
+#define _PAGE_DIRTY                 (1<<2)  /* The MIPS dirty bit      */
+#define _PAGE_SILENT_WRITE          (1<<2)
+#define _CACHE_MASK                 (7<<3)
+
+/* MIPS32 defines only values 2 and 3. The rest are implementation
+ * dependent.
+ */
+#define _CACHE_UNCACHED             (2<<3)
+#define _CACHE_CACHABLE_NONCOHERENT (3<<3)
+
+#else
+
  #define _PAGE_PRESENT               (1<<0)  /* implemented in software */
  #define _PAGE_READ                  (1<<1)  /* implemented in software */
  #define _PAGE_WRITE                 (1<<2)  /* implemented in software */
@@ -97,6 +122,7 @@

  #endif
  #endif
+#endif /* defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR) */

  #define __READABLE	(_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
  #define __WRITEABLE	(_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
@@ -113,6 +139,10 @@
  #define PAGE_CACHABLE_DEFAULT	_CACHE_CACHABLE_COW
  #endif

+#if defined(CONFIG_CPU_MIPS32) && defined(CONFIG_64BIT_PHYS_ADDR)
+#define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 3)
+#else
  #define CONF_CM_DEFAULT		(PAGE_CACHABLE_DEFAULT >> 9)
+#endif

  #endif /* _ASM_PGTABLE_BITS_H */
Index: include/asm-mips/pgtable.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips/pgtable.h,v
retrieving revision 1.97
diff -u -r1.97 pgtable.h
--- include/asm-mips/pgtable.h	19 Jun 2004 01:39:24 -0000	1.97
+++ include/asm-mips/pgtable.h	19 Sep 2004 22:51:29 -0000
@@ -80,6 +80,34 @@
  #define pte_none(pte)		(!(pte_val(pte) & ~_PAGE_GLOBAL))
  #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)

+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+	ptep->pte_high = pte.pte_high;
+	smp_wmb();
+	ptep->pte_low = pte.pte_low;
+	//printk("pte_high %x pte_low %x\n", ptep->pte_high, ptep->pte_low);
+
+	if (pte_val(pte) & _PAGE_GLOBAL) {
+		pte_t *buddy = ptep_buddy(ptep);
+		/*
+		 * Make sure the buddy is global too (if it's !none,
+		 * it better already be global)
+		 */
+		if (pte_none(*buddy))
+			buddy->pte_low |= _PAGE_GLOBAL;
+	}
+}
+
+static inline void pte_clear(pte_t *ptep)
+{
+	/* Preserve global status for the pair */
+	if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
+		set_pte(ptep, __pte(_PAGE_GLOBAL));
+	else
+		set_pte(ptep, __pte(0));
+}
+#else
  /*
   * Certain architectures need to do special things when pte's
   * within a page table are directly modified.  Thus, the following
@@ -111,6 +139,7 @@
  #endif
  		set_pte(ptep, __pte(0));
  }
+#endif

  /*
   * (pmds are folded into pgds so this doesn't get actually called,
@@ -130,6 +159,79 @@
   * Undefined behaviour if not..
   */
  static inline int pte_user(pte_t pte)	{ BUG(); return 0; }
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline int pte_read(pte_t pte)	{ return (pte).pte_low & 
_PAGE_READ; }
+static inline int pte_write(pte_t pte)	{ return (pte).pte_low & 
_PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte)	{ return (pte).pte_low & 
_PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte)	{ return (pte).pte_low & 
_PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)	{ return (pte).pte_low & 
_PAGE_FILE; }
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
+	(pte).pte_high &= ~_PAGE_SILENT_WRITE;
+	return pte;
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	(pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+	(pte).pte_high &= ~_PAGE_SILENT_READ;
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_WRITE;
+	if ((pte).pte_low & _PAGE_MODIFIED) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_READ;
+	if ((pte).pte_low & _PAGE_ACCESSED) {
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_MODIFIED;
+	if ((pte).pte_low & _PAGE_WRITE) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+		(pte).pte_high |= _PAGE_SILENT_WRITE;
+	}
+	return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+	(pte).pte_low |= _PAGE_ACCESSED;
+	if ((pte).pte_low & _PAGE_READ)
+		(pte).pte_low |= _PAGE_SILENT_READ;
+		(pte).pte_high |= _PAGE_SILENT_READ;
+	return pte;
+}
+#else
  static inline int pte_read(pte_t pte)	{ return pte_val(pte) & 
_PAGE_READ; }
  static inline int pte_write(pte_t pte)	{ return pte_val(pte) & 
_PAGE_WRITE; }
  static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & 
_PAGE_MODIFIED; }
@@ -191,6 +293,7 @@
  		pte_val(pte) |= _PAGE_SILENT_READ;
  	return pte;
  }
+#endif

  /*
   * Macro to make mark a page protection value as "uncacheable".  Note
@@ -215,10 +318,20 @@
   */
  #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))

+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_MIPS32)
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte.pte_low &= _PAGE_CHG_MASK;
+	pte.pte_low |= pgprot_val(newprot);
+	pte.pte_high |= pgprot_val(newprot) & 0x3f;
+	return pte;
+}
+#else
  static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
  {
  	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
  }
+#endif


  extern void __update_tlb(struct vm_area_struct *vma, unsigned long 
address,
@@ -245,7 +358,27 @@
   */
  #define HAVE_ARCH_UNMAPPED_AREA

+#ifdef CONFIG_64BIT_PHYS_ADDR
+extern phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size);
+
+extern int remap_page_range_high(struct vm_area_struct *vma,
+		unsigned long from,
+		phys_t phys_addr,
+		unsigned long size,
+		pgprot_t prot);
+
+static inline int io_remap_page_range(struct vm_area_struct *vma,
+		unsigned long from,
+		unsigned long phys_addr,
+		unsigned long size,
+		pgprot_t prot)
+{
+	phys_t phys_addr_high = fixup_bigphys_addr(phys_addr, size);
+	return remap_page_range_high(vma, from, phys_addr_high, size, prot);
+}
+#else
  #define io_remap_page_range remap_page_range
+#endif

  /*
   * No page table caches to initialise

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
@ 2004-02-28 22:06 Tommy McCabe
  0 siblings, 0 replies; 80+ messages in thread
From: Tommy McCabe @ 2004-02-28 22:06 UTC (permalink / raw)
  To: linux-8086

[-- Attachment #1: Type: text/plain, Size: 483 bytes --]

This is a patch that fixes three annoying little bugs
in 0.13pre1:

#1, the extra set of parentheses in
elks/arch/i86/boot/setup.S which it won't compile
with;

#2, the extra set of apostrophes in
elks/kernel/printk.c which will cause the kernel to
print out weird messages filled with 0's;

#3, the /mnt/elks in elkscmd/Make.defs is changed to /mnt/test.

__________________________________
Do you Yahoo!?
Get better spam protection with Yahoo! Mail.
http://antispam.yahoo.com/tools

[-- Attachment #2: patch.diff --]
[-- Type: application/octet-stream, Size: 1348 bytes --]

Index: elks/arch/i86/boot/setup.S
===================================================================
RCS file: /cvsroot/elks/elks/arch/i86/boot/setup.S,v
retrieving revision 1.11
diff -u -r1.11 setup.S
--- elks/arch/i86/boot/setup.S	13 Jul 2002 06:35:36 -0000	1.11
+++ elks/arch/i86/boot/setup.S	28 Feb 2004 21:39:43 -0000
@@ -585,7 +585,7 @@
 	or	al,al
 	jnz	is486
 #endif
-#ifdef(CONFIG_CPU_80386)
+#ifdef CONFIG_CPU_80386
         mov cl,#7
 	lea	si,p80386
 	br	getfpu
Index: elks/kernel/printk.c
===================================================================
RCS file: /cvsroot/elks/elks/kernel/printk.c,v
retrieving revision 1.19
diff -u -r1.19 printk.c
--- elks/kernel/printk.c	12 Jul 2003 19:08:33 -0000	1.19
+++ elks/kernel/printk.c	28 Feb 2004 21:39:43 -0000
@@ -136,7 +136,7 @@
 		continue;
 	    }
 
-	    width = zero = '0';
+	    width = zero = 0;
 	    if (c == '0')
 		zero++;
 	    while (c >= '0' && c <= '9') {
Index: elkscmd/Make.defs
===================================================================
RCS file: /cvsroot/elks/elkscmd/Make.defs,v
retrieving revision 1.15
diff -u -r1.15 Make.defs
--- elkscmd/Make.defs	3 Mar 2002 23:17:05 -0000	1.15
+++ elkscmd/Make.defs	28 Feb 2004 21:39:44 -0000
@@ -159,7 +159,7 @@
 endif
 
 ifeq ($(TARGET_MODE),LOOP)
-TARGET_MNT=/mnt/elks
+TARGET_MNT=/mnt/test
 LOOP=-o loop
 endif
 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-02-22 16:08 ` PATCH Kronos
@ 2004-02-22 19:03   ` Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2004-02-22 19:03 UTC (permalink / raw)
  To: kronos; +Cc: linux-fbdev-devel

On Sun, 2004-02-22 at 08:08, Kronos wrote:
> Il Sat, Feb 21, 2004 at 04:44:37PM -0800, Pete Popov ha scritto: 
> > diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/Config.in linux-2.4-dev/drivers/video/Config.in
> > --- linux-2.4-orig/drivers/video/Config.in	2004-01-13 21:51:28.000000000 -0800
> > +++ linux-2.4-dev/drivers/video/Config.in	2004-02-21 16:19:24.000000000 -0800
> > @@ -159,6 +159,7 @@
> >  	    bool '    SIS 300 series support' CONFIG_FB_SIS_300
> >  	    bool '    SIS 315/330 series support' CONFIG_FB_SIS_315
> >  	 fi
> > +	 bool '  SiliconMotion 501 Driver' CONFIG_FB_SMI501
> >  	 tristate '  NeoMagic display support (EXPERIMENTAL)' CONFIG_FB_NEOMAGIC
> >  	 tristate '  3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
> >  	 tristate '  3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1
> 
> Why bool? It doesn't work as a module?

It hasn't been tested as a module that I know of. If the driver is
otherwise acceptable for inclusion in 2.4, I'll test it as a module if
necessary.

Pete



-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2004-02-22  0:44 PATCH Pete Popov
@ 2004-02-22 16:08 ` Kronos
  2004-02-22 19:03   ` PATCH Pete Popov
  0 siblings, 1 reply; 80+ messages in thread
From: Kronos @ 2004-02-22 16:08 UTC (permalink / raw)
  To: Pete Popov; +Cc: linux-fbdev-devel

Il Sat, Feb 21, 2004 at 04:44:37PM -0800, Pete Popov ha scritto: 
> diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/Config.in linux-2.4-dev/drivers/video/Config.in
> --- linux-2.4-orig/drivers/video/Config.in	2004-01-13 21:51:28.000000000 -0800
> +++ linux-2.4-dev/drivers/video/Config.in	2004-02-21 16:19:24.000000000 -0800
> @@ -159,6 +159,7 @@
>  	    bool '    SIS 300 series support' CONFIG_FB_SIS_300
>  	    bool '    SIS 315/330 series support' CONFIG_FB_SIS_315
>  	 fi
> +	 bool '  SiliconMotion 501 Driver' CONFIG_FB_SMI501
>  	 tristate '  NeoMagic display support (EXPERIMENTAL)' CONFIG_FB_NEOMAGIC
>  	 tristate '  3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
>  	 tristate '  3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1

Why bool? It doesn't work as a module?

Luca
-- 
Home: http://kronoz.cjb.net
Non ho ancora capito se il mio cane e` maschio o femmina:
quando fa la pipi` si chiude in bagno


-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2004-02-22  0:44 Pete Popov
  2004-02-22 16:08 ` PATCH Kronos
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2004-02-22  0:44 UTC (permalink / raw)
  To: linux-fbdev-devel; +Cc: pete_popov


This is a 2.4 patch for the SMI 501 chip. I don't know if anyone is
interested in applying it and/or using it, but I thought I'd send it.
The driver has been tested on the AMD Mirage platform. The I2C portion
of the driver has been sent to the I2C maintainer. 

Pete

diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/Config.in linux-2.4-dev/drivers/video/Config.in
--- linux-2.4-orig/drivers/video/Config.in	2004-01-13 21:51:28.000000000 -0800
+++ linux-2.4-dev/drivers/video/Config.in	2004-02-21 16:19:24.000000000 -0800
@@ -159,6 +159,7 @@
 	    bool '    SIS 300 series support' CONFIG_FB_SIS_300
 	    bool '    SIS 315/330 series support' CONFIG_FB_SIS_315
 	 fi
+	 bool '  SiliconMotion 501 Driver' CONFIG_FB_SMI501
 	 tristate '  NeoMagic display support (EXPERIMENTAL)' CONFIG_FB_NEOMAGIC
 	 tristate '  3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX
 	 tristate '  3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/fbmem.c linux-2.4-dev/drivers/video/fbmem.c
--- linux-2.4-orig/drivers/video/fbmem.c	2004-01-13 21:51:28.000000000 -0800
+++ linux-2.4-dev/drivers/video/fbmem.c	2004-02-21 16:19:24.000000000 -0800
@@ -145,6 +145,8 @@
 extern int sstfb_setup(char*);
 extern int it8181fb_init(void);
 extern int it8181fb_setup(char*);
+extern int smi501fb_init(void);
+extern int smi501fb_setup(char*);
 
 static struct {
 	const char *name;
@@ -254,6 +256,9 @@
 #ifdef CONFIG_FB_VESA
 	{ "vesa", vesafb_init, vesafb_setup },
 #endif 
+#ifdef CONFIG_FB_SMI501
+	{ "smi501fb", smi501fb_init, smi501fb_setup },
+#endif
 
 	/*
 	 * Chipset specific drivers that don't use resource management (yet)
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/Makefile linux-2.4-dev/drivers/video/Makefile
--- linux-2.4-orig/drivers/video/Makefile	2004-01-13 21:51:28.000000000 -0800
+++ linux-2.4-dev/drivers/video/Makefile	2004-02-21 16:19:24.000000000 -0800
@@ -88,6 +88,7 @@
 obj-$(CONFIG_FB_TX3912)           += tx3912fb.o
 obj-$(CONFIG_FB_AU1100)		  += au1100fb.o fbgen.o
 obj-$(CONFIG_FB_IT8181)		  += it8181fb.o fbgen.o
+obj-$(CONFIG_FB_SMI501)           += smi501fb.o fbgen.o
 
 subdir-$(CONFIG_STI_CONSOLE)      += sti
 ifeq ($(CONFIG_STI_CONSOLE),y)
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/smi501fb.c linux-2.4-dev/drivers/video/smi501fb.c
--- linux-2.4-orig/drivers/video/smi501fb.c	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4-dev/drivers/video/smi501fb.c	2004-02-21 16:29:07.000000000 -0800
@@ -0,0 +1,801 @@
+/***************************************************************************
+        smifb.c  -  Silicon Motion, Inc. LynxEM+ frame buffer device
+                             -------------------
+    begin                : Thu Aug 9 2001
+    copyright            : (C) 2001 by Szu-Tao Huang
+    email                : johuang@siliconmotion.com
+    
+    Updated to SM501 by Eric.Devolder@amd.com and dan@embeddededge.com
+    for the AMD Mirage Portable Tablet.  20 Oct 2003
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+
+static char *SMIRegs;		// point to virtual Memory Map IO starting address
+static char *SMILFB;		// point to virtual video memory starting address
+static struct smifb_info fb_info;
+static struct smifb_par current_par;	// used to record hardware information
+static struct display disp;
+
+#include "smi501fb.h"
+
+static int initdone = 0;
+
+static int
+smifb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+              u_long arg, int con, struct fb_info *info)
+{
+	unsigned char	bcmd, status;
+	unsigned int	bval;
+	struct	smireg_op	sreg;
+	int	retval;
+
+	retval = 0;
+	if (cmd == 1) {
+		/* Send command to battery charger.
+		*/
+		bcmd = (unsigned char)arg;
+
+		/* 0x22 is the slave address.
+		*/
+		smi_mmiowb(0x22, I2C_SLAVE_ADDRESS);
+		wmb();
+		smi_mmiowb(bcmd, I2C_DATA);
+		wmb();
+		smi_mmiowb(0, I2C_BYTE_COUNT);	/* byte count - 1 */
+		wmb();
+		smi_mmiowb(0x05, I2C_CONTROL);	/* enable, 100kHz, start */
+		wmb();
+		do {
+			status = smi_mmiorb(I2C_STATUS_RESET);
+			wmb();
+		} while (status == 0);
+		smi_mmiowb(0x00, I2C_CONTROL);	/* enable, 100kHz, stop */
+		if (status & 0x40)
+			smi_mmiowb(0x00, I2C_STATUS_RESET);
+	}
+	else if (cmd == 2) {
+		/* Read results of command.
+		*/
+		smi_mmiowb(0x23, I2C_SLAVE_ADDRESS);
+		wmb();
+		smi_mmiowb(1, I2C_BYTE_COUNT);	/* byte count - 1 */
+		wmb();
+		smi_mmiowb(0x05, I2C_CONTROL);	/* enable, 100kHz, start */
+		wmb();
+		do {
+			status = smi_mmiorb(I2C_STATUS_RESET);
+			wmb();
+		} while (status == 0);
+		bval = smi_mmiorl(I2C_DATA);
+		wmb();
+		smi_mmiowb(0x00, I2C_CONTROL);	/* enable, 100kHz, stop */
+		wmb();
+		if (copy_to_user((char *)arg, &bval, 4))
+			retval = -EFAULT;
+		if (status & 0x40)
+			smi_mmiowb(0x00, I2C_STATUS_RESET);
+	}
+	else if (cmd == 3) {	/* Debug test */
+		bval = smi_mmiorl(GPIO_DATA_HI);
+		bval ^= 0x0000c000;
+		smi_mmiowl(bval, GPIO_DATA_HI);
+
+	}
+	else if (cmd == 4) {	/* Register operation */
+		if (copy_from_user(&sreg, (void *)arg, sizeof(struct smireg_op))) {
+			return -EFAULT;
+		}
+
+		/* Just 32-bit access for now.
+		*/
+		if (sreg.sr_op == SMI_LOAD_REG) {
+			sreg.sr_val = smi_mmiorl(sreg.sr_reg);
+		}
+		else if (sreg.sr_op == SMI_STORE_REG) {
+			smi_mmiowl(sreg.sr_val, sreg.sr_reg);
+		}
+		else if (sreg.sr_op == SMI_AND_REG) {
+			bval = smi_mmiorl(sreg.sr_reg);
+			smi_mmiowl((bval & sreg.sr_val), sreg.sr_reg);
+			sreg.sr_val = bval;
+		}
+		else if (sreg.sr_op == SMI_OR_REG) {
+			bval = smi_mmiorl(sreg.sr_reg);
+			smi_mmiowl((bval | sreg.sr_val), sreg.sr_reg);
+			sreg.sr_val = bval;
+		}
+		else {
+			retval = -EINVAL;
+		}
+		if (copy_to_user((void *)arg, &sreg, sizeof(struct smireg_op))) {
+			retval = -EFAULT;
+		}
+	}
+	else {
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
+
+static int
+smifb_mmap(struct fb_info *_fb,
+         struct file *file,
+         struct vm_area_struct *vma)
+{
+	unsigned int len;
+	unsigned long start=0, off;
+	struct smifb_info *fb = (struct smifb_info *)_fb;
+
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
+		return -EINVAL;
+	}
+
+	start = fb->fb_phys & PAGE_MASK;
+	len = PAGE_ALIGN((start & ~PAGE_MASK) + fb->fb_size);
+
+	off = vma->vm_pgoff << PAGE_SHIFT;
+
+	if ((vma->vm_end - vma->vm_start + off) > len) {
+		return -EINVAL;
+	}
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+
+	pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
+	pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
+
+	/* This is an IO map - tell maydump to skip this VMA */
+	vma->vm_flags |= VM_IO;
+
+	if (io_remap_page_range(vma->vm_start, off,
+                vma->vm_end - vma->vm_start,
+                vma->vm_page_prot)) {
+		return -EAGAIN;
+	}
+
+	fb->mmaped = 1;
+	return 0;
+}
+
+static struct fb_ops smifb_ops = {
+	owner:			THIS_MODULE,
+	fb_get_fix:		fbgen_get_fix,
+	fb_get_var:		fbgen_get_var,
+	fb_set_var:		fbgen_set_var,
+	fb_get_cmap:		fbgen_get_cmap,
+	fb_set_cmap:		fbgen_set_cmap,
+	fb_pan_display:		fbgen_pan_display,
+	fb_ioctl:		smifb_ioctl,
+	fb_mmap:		smifb_mmap,
+};
+
+static void smi_nocursor(struct display *p, int mode, int xx, int yy){};
+
+static void
+smi_detect (void)
+{
+	/*
+	 *  This function should detect the current video mode settings
+	 *  and store it as the default video mode
+	 */
+
+	/*
+	 * Yeh, well, we're not going to change any settings so we're
+	 * always stuck with the default ...
+	 */
+}
+
+static int
+smi_encode_fix(struct fb_fix_screeninfo *fix,
+        const void *_par, struct fb_info_gen *_info)
+{
+	struct smifb_info *info = (struct smifb_info *) _info;
+	struct smifb_par *par = (struct smifb_par *) _par;
+	struct fb_var_screeninfo *var = &par->var;
+
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+	fix->smem_start = info->fb_phys;
+	fix->smem_len = info->fb_size;
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	fix->type_aux = 0;
+	fix->visual = (var->bits_per_pixel == 8) ?
+            FB_VISUAL_PSEUDOCOLOR   : FB_VISUAL_TRUECOLOR;
+	fix->ywrapstep = 0;
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+	fix->line_length = current_par.line_length;
+	return 0;
+}
+
+static void
+set_color_bitfields(struct fb_var_screeninfo *var)
+{
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:    /* RGB 565 */
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	}
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+}
+
+static int
+smi_decode_var(const struct fb_var_screeninfo *var,
+        void *_par, struct fb_info_gen *_info)
+{
+
+	struct smifb_par *par = (struct smifb_par *)_par;
+
+	/*
+	 * Don't allow setting any of these yet: xres and yres don't
+	 * make sense for LCD panels.
+	 */
+/*
+	if (var->xres != p_lcd->xres || var->yres != p_lcd->yres ||
+			var->xres != p_lcd->xres || var->yres != p_lcd->yres) {
+		return -EINVAL;
+	}
+	if(var->bits_per_pixel != p_lcd->bpp) {
+		return -EINVAL;
+	} */
+
+	memset(par, 0, sizeof(struct smifb_par));
+	par->var = *var;
+
+	/* FIXME */
+	switch (var->bits_per_pixel) {
+	case 8:
+		par->var.bits_per_pixel = 8;
+		break;
+	case 16:
+		par->var.bits_per_pixel = 16;
+		break;
+	default:
+		printk("color depth %d bpp not supported\n",
+						var->bits_per_pixel);
+		return -EINVAL;
+
+	}
+	set_color_bitfields(&par->var);
+	par->cmap_len = (par->var.bits_per_pixel == 8) ? 256 : 16;
+	return 0;
+}
+
+static int
+smi_encode_var(struct fb_var_screeninfo *var,
+        const void *par, struct fb_info_gen *_info)
+{
+	*var = ((struct smifb_par *)par)->var;
+	return 0;
+}
+
+static void
+smi_get_par(void *_par, struct fb_info_gen *_info)
+{
+	*(struct smifb_par *)_par = current_par;
+}
+
+static void
+smi_set_par(const void *par, struct fb_info_gen *info)
+{
+	/* nothing to do: we don't change any settings */
+}
+
+static int
+smi_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+             unsigned *blue, unsigned *transp,
+             struct fb_info *info)
+{
+	struct smifb_info* i = (struct smifb_info*)info;
+
+	if (regno > 255)
+		return 1;
+
+	*red    = i->palette[regno].red;
+	*green  = i->palette[regno].green;
+	*blue   = i->palette[regno].blue;
+	*transp = 0;
+
+	return 0;
+}
+
+static int
+smi_setcolreg(unsigned regno, unsigned red, unsigned green,
+	unsigned blue, unsigned transp,
+	struct fb_info *info)
+{
+	struct smifb_info* i = (struct smifb_info *)info;
+
+	if (regno > 255)
+		return 1;
+
+	i->palette[regno].red    = red;
+	i->palette[regno].green  = green;
+	i->palette[regno].blue   = blue;
+
+	switch(current_par.var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		red >>= 10;
+		green >>= 10;
+		blue >>= 10;
+			// FIX!!! fill palette
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		i->fbcon_cmap16[regno] =
+		    ((red & 0xf800) >> 0) |
+		    ((green & 0xfc00) >> 5) |
+		    ((blue & 0xf800) >> 11);
+		break;
+#endif
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int
+smi_blank(int blank_mode, struct fb_info_gen *_info)
+{
+	switch (blank_mode) {
+	case VESA_NO_BLANKING:
+		/* turn on panel */
+		break;
+	case VESA_VSYNC_SUSPEND:
+	case VESA_HSYNC_SUSPEND:
+	case VESA_POWERDOWN:
+		/* turn off panel */
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+static void
+smi_set_disp(const void *unused, struct display *disp,
+             struct fb_info_gen *info)
+{
+	disp->screen_base = (char *)fb_info.fb_virt_start;
+
+	switch (disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		disp->dispsw = &fbcon_cfb8;
+		//fbcon_cfb8.cursor = smi_nocursor;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		disp->dispsw = &fbcon_cfb16;
+		disp->dispsw_data = fb_info.fbcon_cmap16;
+		//fbcon_cfb16.cursor = smi_nocursor;
+		break;
+#endif
+	default:
+		disp->dispsw = &fbcon_dummy;
+		disp->dispsw_data = NULL;
+		break;
+    }
+}
+
+static int
+smi_pan_display(const struct fb_var_screeninfo *var,
+               struct fb_info_gen *info)
+{
+	return 0;
+}
+
+static struct fbgen_hwswitch smi_switch = {
+	detect:		smi_detect,
+	encode_fix:	smi_encode_fix,
+	decode_var:	smi_decode_var,
+	encode_var:	smi_encode_var,
+	get_par:	smi_get_par,
+	set_par:	smi_set_par,
+	getcolreg:	smi_getcolreg,
+	setcolreg:	smi_setcolreg,
+	pan_display:	smi_pan_display,
+	blank:		smi_blank,
+	set_disp:	smi_set_disp
+};
+
+/* GPIO functions to set/clear bits and direction for the bit-bang
+ * I2C algorithm.  Someday, these will need to be protected with
+ * spinlocks/irq.  Right now, I2C is the only one to modify GPIOs.
+ */
+void
+smi501_set_gpio_hi_data(unsigned int val)
+{
+	unsigned int reg;
+
+	reg = smi_mmiorl(GPIO_DATA_HI);
+	wmb();
+	reg |= val;
+	smi_mmiowl(reg, GPIO_DATA_HI);
+	wmb();
+}
+
+void
+smi501_clr_gpio_hi_data(unsigned int val)
+{
+	unsigned int new;
+
+	new = smi_mmiorl(GPIO_DATA_HI);
+	wmb();
+	new &= ~val;
+	smi_mmiowl(new, GPIO_DATA_HI);
+	wmb();
+}
+
+unsigned int
+smi501_get_gpio_hi_data(unsigned int mask)
+{
+	unsigned int new;
+
+	new = smi_mmiorl(GPIO_DATA_HI);
+	wmb();
+
+	return (new & mask);
+}
+
+void
+smi501_set_gpio_hi_direction(unsigned int mask, unsigned int val)
+{
+	unsigned int new;
+
+	new = smi_mmiorl(GPIO_DATA_DIR_HI);
+	wmb();
+	new &= ~mask;
+	new |= val;
+	smi_mmiowl(new, GPIO_DATA_DIR_HI);
+	wmb();
+}
+
+
+/* This function still needs lots of work to generically support
+ * different output devices (CRT or LCD) and resolutions.
+ * Currently hard-coded for Mirage 1024x768 LCD panel.
+ */
+static void
+smi_setmode(struct smifb_info *sfb,struct smifb_par *hw)
+{
+	uint	reg;
+
+	if (initdone)
+		return;
+
+	initdone = 1;
+
+	/* Just blast in some control values based upon the chip
+	 * documentation.  We use the internal memory, I don't know
+	 * how to determine the amount available yet.
+	 */
+	smi_mmiowl(0x07F127C2, DRAM_CTRL);
+	smi_mmiowl(0x02000020, PANEL_HWC_ADDRESS);
+	smi_mmiowl(0x007FF800, PANEL_HWC_ADDRESS);
+	smi_mmiowl(0x00021827, POWER_MODE1_GATE);
+	smi_mmiowl(0x011A0A09, POWER_MODE1_CLOCK);
+	smi_mmiowl(0x00000001, POWER_MODE_CTRL);
+	smi_mmiowl(0x80000000, PANEL_FB_ADDRESS);
+	smi_mmiowl(0x08000800, PANEL_FB_WIDTH);
+	smi_mmiowl(0x04000000, PANEL_WINDOW_WIDTH);
+	smi_mmiowl(0x03000000, PANEL_WINDOW_HEIGHT);
+	smi_mmiowl(0x00000000, PANEL_PLANE_TL);
+	smi_mmiowl(0x02FF03FF, PANEL_PLANE_BR);
+	smi_mmiowl(0x05D003FF, PANEL_HORIZONTAL_TOTAL);
+	smi_mmiowl(0x00C80424, PANEL_HORIZONTAL_SYNC);
+	smi_mmiowl(0x032502FF, PANEL_VERTICAL_TOTAL);
+	smi_mmiowl(0x00060302, PANEL_VERTICAL_SYNC);
+	smi_mmiowl(0x00013905, PANEL_DISPLAY_CTRL);
+	smi_mmiowl(0x01013105, PANEL_DISPLAY_CTRL);
+	waitforvsync();
+	smi_mmiowl(0x03013905, PANEL_DISPLAY_CTRL);
+	waitforvsync();
+	smi_mmiowl(0x07013905, PANEL_DISPLAY_CTRL);
+	waitforvsync();
+	smi_mmiowl(0x0F013905, PANEL_DISPLAY_CTRL);
+	smi_mmiowl(0x0002187F, POWER_MODE1_GATE);
+	smi_mmiowl(0x01011801, POWER_MODE1_CLOCK);
+	smi_mmiowl(0x00000001, POWER_MODE_CTRL);
+
+	smi_mmiowl(0x80000000, PANEL_FB_ADDRESS);
+	smi_mmiowl(0x00000000, PANEL_PAN_CTRL);
+	smi_mmiowl(0x00000000, PANEL_COLOR_KEY);
+
+	/* Enable I2C in GPIO.
+	*/
+#if 0
+	reg = smi_mmiorl(GPIO_HI_CTRL);
+	wmb();
+	reg |= 0x0000c000;		/* Enable bits 46, 47 */
+	smi_mmiowl(reg, GPIO_HI_CTRL);
+	wmb();
+	smi_mmiowb(0x00, I2C_CONTROL);	/* enable, 100kHz, stop */
+	wmb();
+	smi_mmiowb(0x00, I2C_STATUS_RESET);
+#else
+	/* Enable GPIO pins and make them inputs.
+	*/
+	reg = smi_mmiorl(GPIO_DATA_DIR_HI);
+	wmb();
+	reg &= ~0x0000c000;		/* Enable bits 46, 47 */
+	smi_mmiowl(reg, GPIO_DATA_DIR_HI);
+	reg = smi_mmiorl(GPIO_HI_CTRL);
+	wmb();
+	reg &= ~0x0000c000;		/* Enable bits 46, 47 */
+	smi_mmiowl(reg, GPIO_HI_CTRL);
+	wmb();
+	reg = smi_mmiorl(GPIO_DATA_HI);
+	wmb();
+	reg |= 0x0000c000;		/* Let 'em float */
+	smi_mmiowl(reg, GPIO_DATA_HI);
+#endif
+
+	/* Enable 8-bit ZV Port.
+	*/
+	reg = smi_mmiorl(GPIO_LO_CTRL);
+	wmb();
+	reg |= 0x00ff0000;		/* Enable bits 16-23 */
+	smi_mmiowl(reg, GPIO_LO_CTRL);
+	wmb();
+}
+
+/* Set up the zv port to be displayed on the screen.  Currently
+ * coded to expect CCIR 656, YUV 4:2:2 cosited from the PNX1302.
+ */
+static void
+set_videoport(int loc_x, int loc_y, int size_x, int size_y)
+{
+	int nbytes;
+	int top, left, bot, right;
+
+	/* Initialize registers, most power up undefined.
+	*/
+	smi_mmiowl(0x0014008a, ZV_CAPTURE_CLIP);
+	smi_mmiowl(((size_y << 16) | size_x), ZV_CAPTURE_SIZE);
+
+	/* Magic buffer addresses.  Just ensure they don't
+	 * collide with something else in memory.
+	 */
+	smi_mmiowl(0x00200000, ZV_CAPTURE_BUF0);
+	smi_mmiowl(0x00400000, ZV_CAPTURE_BUF1);
+	smi_mmiowl(0x00000000, ZV_CAPTURE_OFFSET);
+	smi_mmiowl(0x00000004, ZV_FIFO_CTRL);
+
+#if 0
+	smi_mmiowl(0x00016007, VIDEO_DISPLAY_CTRL);
+#else
+	smi_mmiowl(0x00010005, VIDEO_DISPLAY_CTRL);
+#endif
+	smi_mmiowl(0x00400000, VIDEO_DISPLAY_FB0);
+	smi_mmiowl(0x00400000, VIDEO_DISPLAY_FB1);
+	smi_mmiowl(((size_x * 2) << 16), VIDEO_DISPLAY_FBWIDTH);
+	nbytes = (size_x * 2) * size_y;
+	nbytes += 127;
+	nbytes &= ~127;
+	smi_mmiowl(0x00400000 + nbytes, VIDEO_DISPLAY_FB0LAST);
+	smi_mmiowl(0x00400000 + nbytes, VIDEO_DISPLAY_FB1LAST);
+
+
+	top = loc_y;
+	left = loc_x;
+	smi_mmiowl(((top << 16) | left), VIDEO_DISPLAY_TL);
+
+	/* Use max ntsc.
+	*/
+	bot = top + size_y;
+	right = left + size_x;
+	smi_mmiowl(((bot << 16) | right), VIDEO_DISPLAY_BR);
+
+	smi_mmiowl(0x00000000, VIDEO_SCALE);
+	smi_mmiowl(0x00000000, VIDEO_INITIAL_SCALE);
+
+	smi_mmiowl(0x00ededed, VIDEO_YUV_CONSTANTS);
+
+	smi_mmiowl(0x17010000, VIDEO_ALPHA_CTRL);
+
+	/* Enable
+	*/
+#if 0
+	smi_mmiowl(0x00000211, ZV_CAPTURE_CTRL);
+#endif
+
+}
+
+/*
+ * Unmap in the memory mapped IO registers
+ *
+ */
+
+static void __devinit
+smi_unmap_mmio(struct smifb_info *sfb)
+{
+	if (sfb && SMIRegs) {
+		iounmap(SMIRegs);
+		SMIRegs = NULL;
+	}
+}
+
+
+/*
+ * Unmap in the screen memory
+ *
+ */
+static void __devinit
+smi_unmap_smem(struct smifb_info *sfb)
+{
+	if (sfb && sfb->fb_virt_start) {
+		iounmap(sfb->fb_virt_start);
+		sfb->fb_virt_start = NULL;
+	}
+}
+
+void
+smi501fb_setup (char *options, int *ints)
+{
+	return;
+}
+
+int __init smi501fb_init(void)
+{
+	struct smifb_info *sfb;
+	char name[16];
+	int err;
+
+	struct pci_dev *pdev = NULL;
+	int i = 0;
+
+	/* Find and enable Voyager
+	 * Rev. AA is 0x501, Rev. B is 0x510.
+	 */
+	pdev = pci_find_device(0x126f,0x510, pdev);
+	if (pdev == NULL)
+		pdev = pci_find_device(0x126f,0x501, pdev);
+	if (pdev == NULL)
+		return -ENODEV;
+	
+	/* Enable the chip.
+	*/
+	err = pci_enable_device(pdev);
+	if (err)
+		return err;
+	current_par.chipID = 0x510;
+
+	err = -ENOMEM;
+	sprintf(name, "smifb");
+	sfb = &fb_info;
+	memset(sfb, 0, sizeof(struct smifb_info));
+	memset(&disp, 0, sizeof(struct display));
+
+	sfb->currcon = -1;
+	sfb->dev = pdev;
+
+
+	/* Set up MMIO space.
+	*/
+	sfb->mmio_phys = pci_resource_start(pdev,1);
+	sfb->mmio_size = 0x00200000;
+	sfb->mmio_virt_start = ioremap(sfb->mmio_phys, sfb->mmio_size);
+	SMIRegs = sfb->mmio_virt_start;
+
+	/* Set up framebuffer.  It's a 64M space, various amount of
+	 * internal memory.  I don't know how to determine the real
+	 * amount of memory (yet).
+	 */
+	sfb->fb_phys = pci_resource_start(pdev,0);
+	sfb->fb_size = 0x00800000;
+	sfb->fb_virt_start = ioremap(sfb->fb_phys, sfb->fb_size);
+	SMILFB = sfb->fb_virt_start;
+
+	 memset((void *)fb_info.fb_virt_start, 0, fb_info.fb_size);
+
+	current_par.var.xres =
+   	current_par.var.xres_virtual = 1024; //sfb->fb.var.xres;
+	current_par.var.yres =
+	current_par.var.yres_virtual = 768; //sfb->fb.var.yres;
+	current_par.var.bits_per_pixel = 16; //sfb->fb.var.bits_per_pixel;
+	current_par.line_length = (current_par.var.bits_per_pixel * current_par.var.xres) / 8;
+
+	smi_setmode(sfb, &current_par);
+
+	fb_info.gen.parsize = sizeof(struct smifb_par);
+	fb_info.gen.fbhw = &smi_switch;
+
+	strcpy(fb_info.gen.info.modename, "SMI Voyager");
+	fb_info.gen.info.changevar = NULL;
+	fb_info.gen.info.node = -1;
+
+	fb_info.gen.info.fbops = &smifb_ops;
+	fb_info.gen.info.disp = &disp;
+	fb_info.gen.info.switch_con = &fbgen_switch;
+	fb_info.gen.info.updatevar = &fbgen_update_var;
+	fb_info.gen.info.blank = &fbgen_blank;
+	fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
+
+	/* This should give a reasonable default video mode
+	*/
+	fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+	fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+	fbgen_set_disp(-1, &fb_info.gen);
+	fbgen_install_cmap(0, &fb_info.gen);
+
+	if (register_framebuffer(&fb_info.gen.info) < 0)
+		goto failed;
+
+#if 0
+	/* This is for videoport testing.  The Mirage uses an 8-bit
+	 * video port, which is now known to not work properly
+	 * on the SMI501 part.
+	 */
+	set_videoport(150, 150, 768, 576);
+#endif
+
+	MOD_INC_USE_COUNT;
+	printk("Silicon Motion Inc. VOYAGER Init complete.\n");
+
+	return 0;
+
+failed:
+	smi_unmap_smem(sfb);
+	smi_unmap_mmio(sfb);
+
+	return err;
+}
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/smi501fb.h linux-2.4-dev/drivers/video/smi501fb.h
--- linux-2.4-orig/drivers/video/smi501fb.h	1969-12-31 16:00:00.000000000 -0800
+++ linux-2.4-dev/drivers/video/smi501fb.h	2004-02-21 16:19:24.000000000 -0800
@@ -0,0 +1,171 @@
+/***************************************************************************
+			smifb.h  -  SiliconMotion LynxEM+ frame buffer device
+                             -------------------
+    begin                : Thu Aug 9 2001
+    copyright            : (C) 2001 by Szu-Tao Huang
+    email                : johuang@siliconmotion.com
+    
+    Updated to SM501 by Eric.Devolder@amd.com and dan@embeddededge.com
+    for the AMD Mirage Portable Tablet.  20 Oct 2003
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the 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 <linux/config.h>
+
+#define smi_mmiowb(dat,reg)	writeb(dat, (unsigned int)(SMIRegs + reg))
+#define smi_mmioww(dat,reg)	writew(dat, (unsigned int)(SMIRegs + reg))
+#define smi_mmiowl(dat,reg)	writel(dat, (unsigned int)(SMIRegs + reg))
+
+#define smi_mmiorb(reg)	        readb(SMIRegs + reg)
+#define smi_mmiorw(reg)	        readw(SMIRegs + reg)
+#define smi_mmiorl(reg)	        readl(SMIRegs + reg)
+
+#define NR_PALETTE      256
+
+/* Address space offsets for various control/status registers.
+*/
+#define MISC_CTRL			0x000004
+#define GPIO_LO_CTRL			0x000008
+#define GPIO_HI_CTRL			0x00000c
+#define DRAM_CTRL			0x000010
+#define CURRENT_POWER_GATE		0x000038
+#define CURRENT_POWER_CLOCK		0x00003C
+#define POWER_MODE1_GATE                0x000048
+#define POWER_MODE1_CLOCK               0x00004C
+#define POWER_MODE_CTRL			0x000054
+
+#define GPIO_DATA_LO			0x010000
+#define GPIO_DATA_HI			0x010004
+#define GPIO_DATA_DIR_LO		0x010008
+#define GPIO_DATA_DIR_HI		0x01000c
+#define I2C_BYTE_COUNT			0x010040
+#define I2C_CONTROL			0x010041
+#define I2C_STATUS_RESET		0x010042
+#define I2C_SLAVE_ADDRESS		0x010043
+#define I2C_DATA			0x010044
+
+#define DE_COLOR_COMPARE		0x100020
+#define DE_COLOR_COMPARE_MASK		0x100024
+#define DE_MASKS			0x100028
+#define DE_WRAP				0x10004C
+
+#define PANEL_DISPLAY_CTRL              0x080000
+#define PANEL_PAN_CTRL                  0x080004
+#define PANEL_COLOR_KEY                 0x080008
+#define PANEL_FB_ADDRESS                0x08000C
+#define PANEL_FB_WIDTH                  0x080010
+#define PANEL_WINDOW_WIDTH              0x080014
+#define PANEL_WINDOW_HEIGHT             0x080018
+#define PANEL_PLANE_TL                  0x08001C
+#define PANEL_PLANE_BR                  0x080020
+#define PANEL_HORIZONTAL_TOTAL          0x080024
+#define PANEL_HORIZONTAL_SYNC           0x080028
+#define PANEL_VERTICAL_TOTAL            0x08002C
+#define PANEL_VERTICAL_SYNC             0x080030
+#define PANEL_CURRENT_LINE              0x080034
+#define VIDEO_DISPLAY_CTRL		0x080040
+#define VIDEO_DISPLAY_FB0		0x080044
+#define VIDEO_DISPLAY_FBWIDTH		0x080048
+#define VIDEO_DISPLAY_FB0LAST		0x08004C
+#define VIDEO_DISPLAY_TL		0x080050
+#define VIDEO_DISPLAY_BR		0x080054
+#define VIDEO_SCALE			0x080058
+#define VIDEO_INITIAL_SCALE		0x08005C
+#define VIDEO_YUV_CONSTANTS		0x080060
+#define VIDEO_DISPLAY_FB1		0x080064
+#define VIDEO_DISPLAY_FB1LAST		0x080068
+#define VIDEO_ALPHA_CTRL		0x080080
+#define PANEL_HWC_ADDRESS		0x0800F0
+#define CRT_DISPLAY_CTRL		0x080200
+
+#define ZV_CAPTURE_CTRL			0x090000
+#define ZV_CAPTURE_CLIP			0x090004
+#define ZV_CAPTURE_SIZE			0x090008
+#define ZV_CAPTURE_BUF0			0x09000c
+#define ZV_CAPTURE_BUF1			0x090010
+#define ZV_CAPTURE_OFFSET		0x090014
+#define ZV_FIFO_CTRL			0x090018
+
+#define waitforvsync() udelay(100); udelay(100); udelay(100); udelay(100);
+
+/*
+ * Minimum X and Y resolutions
+ */
+#define MIN_XRES	640
+#define MIN_YRES	480
+
+/*
+* Private structure
+*/
+struct smifb_info
+{
+        /*
+        * The following is a pointer to be passed into the
+        * functions below.  The modules outside the main
+        * smifb.c driver have no knowledge as to what
+        * is within this structure.
+        */
+        struct fb_info_gen          gen;
+        struct display_switch   *dispsw;
+        struct pci_dev	        *dev;
+        signed int              currcon;
+
+        struct {
+                u8 red, green, blue;
+        } palette[NR_PALETTE];
+
+        u_int                   palette_size;
+
+		int mmaped;
+		u32 mmio_phys;
+		u32 mmio_size;
+		char *mmio_virt_start;
+
+		u32 fb_phys;
+		u32 fb_size;
+		char *fb_virt_start;
+
+#if defined(FBCON_HAS_CFB16)
+		u16 fbcon_cmap16[16];
+#endif
+
+		/* smi_alloc_fb_info has struct display + 16*sizeof(u32)
+		*/
+		u32 yyy[16];
+};
+
+struct smifb_par
+{
+	struct fb_var_screeninfo var;
+	int line_length;	/* in bytes */
+	int cmap_len;		/* color-map length */
+
+	/*
+	 * Hardware
+	 */
+	u16		chipID;
+
+	u_int	width;
+	u_int	height;
+	u_int	hz;
+};
+
+/* User access to registers for debug and development.
+*/
+struct smireg_op {
+	uint	sr_op;
+	uint	sr_reg;
+	uint	sr_val;
+};
+
+#define SMI_LOAD_REG	1
+#define SMI_STORE_REG	2
+#define SMI_AND_REG	3
+#define SMI_OR_REG	4





-------------------------------------------------------
SF.Net is sponsored by: Speed Start Your Linux Apps Now.
Build and deploy apps & Web services for Linux with
a free DVD software kit from IBM. Click Now!
http://ads.osdn.com/?ad_id=1356&alloc_id=3438&op=click

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2003-12-01  5:58 patch Diyab
@ 2003-12-01 14:36 ` Stephen Smalley
  0 siblings, 0 replies; 80+ messages in thread
From: Stephen Smalley @ 2003-12-01 14:36 UTC (permalink / raw)
  To: Diyab; +Cc: SELinux

On Mon, 2003-12-01 at 00:58, Diyab wrote:
> Where can one locate the AT_SECURE patch for glibc?  AT_SECURE does not 
> exist in the current version of glibc, there is no patch in the  SE 
> Linux archives and the glibc source RPM from the fedora project contains 
> a patched glibc and not a seperate glibc and patch.

The change was upstreamed into the mainline glibc CVS tree in June.
http://sources.redhat.com/glibc/

-- 
Stephen Smalley <sds@epoch.ncsc.mil>
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* patch
@ 2003-12-01  5:58 Diyab
  2003-12-01 14:36 ` patch Stephen Smalley
  0 siblings, 1 reply; 80+ messages in thread
From: Diyab @ 2003-12-01  5:58 UTC (permalink / raw)
  To: SELinux

Where can one locate the AT_SECURE patch for glibc?  AT_SECURE does not 
exist in the current version of glibc, there is no patch in the  SE 
Linux archives and the glibc source RPM from the fedora project contains 
a patched glibc and not a seperate glibc and patch.

Timothy,

-- 
I put instant coffee in a microwave and almost went back in time.
		-- Steven Wright


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Patch
  2003-11-03 22:45 Patch Frank Borich
@ 2003-11-03 23:00 ` Patrick Mansfield
  0 siblings, 0 replies; 80+ messages in thread
From: Patrick Mansfield @ 2003-11-03 23:00 UTC (permalink / raw)
  To: Frank Borich; +Cc: linux-scsi, David Lethe, Bill Krempp

On Mon, Nov 03, 2003 at 02:45:46PM -0800, Frank Borich wrote:

> numbering.  Because we sell only to OEMs, the Vendor ID will change.
> The logic in scsi_scan.c will not handle a wild card or "NULL" for the
> Vendor ID.  Can we 
> add code to allow a wildcard for this?  The Model "Kashi-II" will remain

Can you instead modify the device to return as SCSI-3?

That is a much better solution. 

And, for 2.6 we will only use REPORT LUNS if the device is SCSI-3 or up.

You could certainly submit a patch for 2.4 and 2.6 to wild card the vendor
field.

-- Patrick Mansfield

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
@ 2003-11-03 22:45 Frank Borich
  2003-11-03 23:00 ` Patch Patrick Mansfield
  0 siblings, 1 reply; 80+ messages in thread
From: Frank Borich @ 2003-11-03 22:45 UTC (permalink / raw)
  To: linux-scsi; +Cc: David Lethe, Bill Krempp

Hi,

I work for a Xyratex International.  We are currently manufacturing a
FC-SATA RAID subsystem called Kashi-II.  We sell only to OEMs, hence we
have run into a problem involving scsi_scan.c and the "device_list[]".
We need to set the BLIST_SPARSELUN flag to support non-contiguous lun
numbering.  Because we sell only to OEMs, the Vendor ID will change.
The logic in scsi_scan.c will not handle a wild card or "NULL" for the
Vendor ID.  Can we 
add code to allow a wildcard for this?  The Model "Kashi-II" will remain
constant across all OEMs.  If we cannot do this, each OEM will have to
submit an entry to this list for 2.4.x support.

Thanks in advance for your time!    

Frank Borich
------------------------------------------------------------------
Systems Engineer
Direct 630 654 6089
Fax 630 325 2513
e-mail frank_borich@us.xyratex.com
 


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Patch
  2003-02-10 16:09 ` Patch Aman
@ 2003-02-10 17:24   ` Matt Porter
  0 siblings, 0 replies; 80+ messages in thread
From: Matt Porter @ 2003-02-10 17:24 UTC (permalink / raw)
  To: Aman; +Cc: linuxppc-embedded


On Mon, Feb 10, 2003 at 09:39:51PM +0530, Aman wrote:
> Can anybody tell me , the website, from where I can download the patches for
> ppc440 bitkeeper kernel.

What sort of patches are you looking for?   The PPC440 support in the
linuxppc_2_4_devel tree is 99% complete and should work.  Some changesets
mention an ftp site where you can obtain a 36-bit mmap patch that couldn't
be added to the tree.

Regards,
--
Matt Porter
porter@cox.net
This is Linux Country. On a quiet night, you can hear Windows reboot.

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
       [not found] <OE58jbP3SIGYF2rEF6f00001796@hotmail.com>
@ 2003-02-10 16:09 ` Aman
  2003-02-10 17:24   ` Patch Matt Porter
  0 siblings, 1 reply; 80+ messages in thread
From: Aman @ 2003-02-10 16:09 UTC (permalink / raw)
  To: linuxppc-embedded


Hi All

Can anybody tell me , the website, from where I can download the patches for
ppc440 bitkeeper kernel.

Thanking you in advance.

Regards
Aman


** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Patch
       [not found] ` <1040837764.2777.8.camel-SH3sQJamR4OeZLLa646FqQ@public.gmane.org>
  2002-12-25 19:10   ` Patch Gregory Gulik
@ 2002-12-26  5:12   ` Theodore Morse
  1 sibling, 0 replies; 80+ messages in thread
From: Theodore Morse @ 2002-12-26  5:12 UTC (permalink / raw)
  To: Mailhebuau Christophe, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

Mailhebuau,

I had this same problem. I compiled the latest acpi
patch into 2.4.20, and did not get an acpi directory
in /proc. This was due to the fact that APM was
initializing first, and ACPI did not try to override
it, even though my BIOS did not support APM. What I
did was not include APM support in the kernel. This
fixed it for me.

Hope this helps. Good luck.

Ted Morse

--- Mailhebuau Christophe <CMailhebuau-GyotsYYSwH0@public.gmane.org>
wrote:
> Hi,
> 
> I have compiled my kernel with acpi support, but i
> don't have
> subdirectory :
> 
> /proc/acpi
> 
> What must i do ?
> 
> apply patch ? and compiled again ?
> 
> what i must used patch, which version ? my kernel is
> 2.4.19-16
> 
> which command i must used to apply patch ?
> -- 
> Cordialement,
> Christophe Mailhebuau    http://www.justlinux.org
>                            http://www.abul.org
> GPG: 1024D/75B07F8D: BD18 2D01 D954 A339 E35B 9EA1
> 4240 0410 75B0 7F8D
> 

> ATTACHMENT part 2 application/pgp-signature
name=signature.asc



=====
Ted Morse
Student/Programmer
University of Evansville/Ciholas Enterprises

__________________________________________________
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: Patch
       [not found] ` <1040837764.2777.8.camel-SH3sQJamR4OeZLLa646FqQ@public.gmane.org>
@ 2002-12-25 19:10   ` Gregory Gulik
  2002-12-26  5:12   ` Patch Theodore Morse
  1 sibling, 0 replies; 80+ messages in thread
From: Gregory Gulik @ 2002-12-25 19:10 UTC (permalink / raw)
  To: Mailhebuau Christophe, acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f


A good start is the "Power Management" section of this page:

http://home.gagme.com/greg/linux/toshiba1115.php

Just make sure you use the appropriate patches for your version of the 
kernel sources...



Mailhebuau Christophe wrote:
> Hi,
> 
> I have compiled my kernel with acpi support, but i don't have
> subdirectory :
> 
> /proc/acpi
> 
> What must i do ?
> 
> apply patch ? and compiled again ?
> 
> what i must used patch, which version ? my kernel is 2.4.19-16
> 
> which command i must used to apply patch ?

-- 
Greg Gulik                                 http://www.gulik.org/greg/
greg-eIr5aKVv5JjYtjvyW6yDsg@public.gmane.org




-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
@ 2002-12-25 17:36 Mailhebuau Christophe
       [not found] ` <1040837764.2777.8.camel-SH3sQJamR4OeZLLa646FqQ@public.gmane.org>
  0 siblings, 1 reply; 80+ messages in thread
From: Mailhebuau Christophe @ 2002-12-25 17:36 UTC (permalink / raw)
  To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

[-- Attachment #1: Type: text/plain, Size: 461 bytes --]

Hi,

I have compiled my kernel with acpi support, but i don't have
subdirectory :

/proc/acpi

What must i do ?

apply patch ? and compiled again ?

what i must used patch, which version ? my kernel is 2.4.19-16

which command i must used to apply patch ?
-- 
Cordialement,
Christophe Mailhebuau    http://www.justlinux.org
                           http://www.abul.org
GPG: 1024D/75B07F8D: BD18 2D01 D954 A339 E35B 9EA1 4240 0410 75B0 7F8D

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-20 20:59   ` PATCH Pete Popov
@ 2002-12-21 20:39     ` James Simmons
  0 siblings, 0 replies; 80+ messages in thread
From: James Simmons @ 2002-12-21 20:39 UTC (permalink / raw)
  To: Pete Popov; +Cc: Ralf Baechle, linux-mips


> > I will be applying these changes to 2.5.X. Just give me some time as I'm 
> > reworking several drivers at one time. Thansk for the patch.
> 
> I assume you're talking about the ragexl patch? I also have an epson
> 1356/86 patch I need to send you.

Could you please. Is this for 2.5.X?

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-20 20:43 ` PATCH James Simmons
@ 2002-12-20 20:59   ` Pete Popov
  2002-12-21 20:39     ` PATCH James Simmons
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2002-12-20 20:59 UTC (permalink / raw)
  To: James Simmons; +Cc: Ralf Baechle, linux-mips

On Fri, 2002-12-20 at 12:43, James Simmons wrote:
> 
> I will be applying these changes to 2.5.X. Just give me some time as I'm 
> reworking several drivers at one time. Thansk for the patch.

I assume you're talking about the ragexl patch? I also have an epson
1356/86 patch I need to send you.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-14  4:52 PATCH Pete Popov
  2002-12-17 22:29 ` PATCH Greg Lindahl
@ 2002-12-20 20:43 ` James Simmons
  2002-12-20 20:59   ` PATCH Pete Popov
  1 sibling, 1 reply; 80+ messages in thread
From: James Simmons @ 2002-12-20 20:43 UTC (permalink / raw)
  To: Pete Popov; +Cc: Ralf Baechle, linux-mips


I will be applying these changes to 2.5.X. Just give me some time as I'm 
reworking several drivers at one time. Thansk for the patch.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-17 22:40   ` PATCH Pete Popov
@ 2002-12-17 23:24     ` Alan Cox
  2002-12-17 22:51       ` PATCH Pete Popov
  0 siblings, 1 reply; 80+ messages in thread
From: Alan Cox @ 2002-12-17 23:24 UTC (permalink / raw)
  To: Pete Popov; +Cc: Greg Lindahl, linux-mips

On Tue, 2002-12-17 at 22:40, Pete Popov wrote:
> It would be if there was a generic way to go about adding support for
> graphics cards that require bios support. In this case we were working
> with the manufacturer and had all the docs, but still couldn't figure
> out certain pieces needed in initializing the card.  Ultimately the "no
> bios init" patch you see is a pci bus analyzer capture, filtered through
> a perl script, dumped into a new file, and integrated as part of the
> driver.  Even if you could do that with all cards, I'm not sure it's
> legally allowed. We had the vendor's blessings in this case.

XFree86 has an emulator library for this.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-17 22:51       ` PATCH Pete Popov
@ 2002-12-17 22:59         ` Greg Lindahl
  0 siblings, 0 replies; 80+ messages in thread
From: Greg Lindahl @ 2002-12-17 22:59 UTC (permalink / raw)
  To: linux-mips

On Tue, Dec 17, 2002 at 02:51:14PM -0800, Pete Popov wrote:

> One of the problems with these graphics cards is that they are end of
> life before you finish writing the driver. I still have a few RageXL
> cards in the office, but you can't even buy them in the store anymore.

Yeah, that's why emulation might turn out to be easier in the long run.

This emulator:

http://www.scitechsoft.com/products/developer/x86_emulator.html

claims to be the one in XFree86 these days. Another emulation project
is bochs. It doesn't really matter if the performance isn't great
since the BIOS doesn't run for very long. But I think I'll have to dig
around a bit to figure out how well this works in practice.

-- greg

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-17 23:24     ` PATCH Alan Cox
@ 2002-12-17 22:51       ` Pete Popov
  2002-12-17 22:59         ` PATCH Greg Lindahl
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2002-12-17 22:51 UTC (permalink / raw)
  To: Alan Cox; +Cc: Greg Lindahl, linux-mips

On Tue, 2002-12-17 at 15:24, Alan Cox wrote:
> On Tue, 2002-12-17 at 22:40, Pete Popov wrote:
> > It would be if there was a generic way to go about adding support for
> > graphics cards that require bios support. In this case we were working
> > with the manufacturer and had all the docs, but still couldn't figure
> > out certain pieces needed in initializing the card.  Ultimately the "no
> > bios init" patch you see is a pci bus analyzer capture, filtered through
> > a perl script, dumped into a new file, and integrated as part of the
> > driver.  Even if you could do that with all cards, I'm not sure it's
> > legally allowed. We had the vendor's blessings in this case.
> 
> XFree86 has an emulator library for this.

Thanks; I didn't know that.

One of the problems with these graphics cards is that they are end of
life before you finish writing the driver. I still have a few RageXL
cards in the office, but you can't even buy them in the store anymore.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-17 22:29 ` PATCH Greg Lindahl
@ 2002-12-17 22:40   ` Pete Popov
  2002-12-17 23:24     ` PATCH Alan Cox
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2002-12-17 22:40 UTC (permalink / raw)
  To: Greg Lindahl; +Cc: linux-mips

On Tue, 2002-12-17 at 14:29, Greg Lindahl wrote:
> On Fri, Dec 13, 2002 at 08:52:47PM -0800, Pete Popov wrote:
> 
> > This patch was sent to the RageXL maintainer but I don't think he was
> > interested in it. Others might find it useful on embedded systems. It
> > initializes the RageXL card when there is no system bios to initialize
> > it from the video bios.  Tested on the Pb1500; makes a really good
> > workstation.
> 
> Pete,
> 
> Is there a website with info about graphics cards on non-x86
> architectures? 

Not that I know of personally.

> Most cards require their own BIOS to be run at boot
> time. This issue ought to be of interest to lots of other communities
> than MIPS.

It would be if there was a generic way to go about adding support for
graphics cards that require bios support. In this case we were working
with the manufacturer and had all the docs, but still couldn't figure
out certain pieces needed in initializing the card.  Ultimately the "no
bios init" patch you see is a pci bus analyzer capture, filtered through
a perl script, dumped into a new file, and integrated as part of the
driver.  Even if you could do that with all cards, I'm not sure it's
legally allowed. We had the vendor's blessings in this case.

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-12-14  4:52 PATCH Pete Popov
@ 2002-12-17 22:29 ` Greg Lindahl
  2002-12-17 22:40   ` PATCH Pete Popov
  2002-12-20 20:43 ` PATCH James Simmons
  1 sibling, 1 reply; 80+ messages in thread
From: Greg Lindahl @ 2002-12-17 22:29 UTC (permalink / raw)
  To: linux-mips

On Fri, Dec 13, 2002 at 08:52:47PM -0800, Pete Popov wrote:

> This patch was sent to the RageXL maintainer but I don't think he was
> interested in it. Others might find it useful on embedded systems. It
> initializes the RageXL card when there is no system bios to initialize
> it from the video bios.  Tested on the Pb1500; makes a really good
> workstation.

Pete,

Is there a website with info about graphics cards on non-x86
architectures? Most cards require their own BIOS to be run at boot
time. This issue ought to be of interest to lots of other communities
than MIPS.

-- greg

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2002-12-14  4:52 Pete Popov
  2002-12-17 22:29 ` PATCH Greg Lindahl
  2002-12-20 20:43 ` PATCH James Simmons
  0 siblings, 2 replies; 80+ messages in thread
From: Pete Popov @ 2002-12-14  4:52 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips


This patch was sent to the RageXL maintainer but I don't think he was
interested in it. Others might find it useful on embedded systems. It
initializes the RageXL card when there is no system bios to initialize
it from the video bios.  Tested on the Pb1500; makes a really good
workstation.

Pete

diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/Config.in linux-2.4/drivers/video/Config.in
--- linux-2.4-orig/drivers/video/Config.in	Wed Nov 13 15:07:55 2002
+++ linux-2.4/drivers/video/Config.in	Wed Dec 11 22:21:31 2002
@@ -138,6 +138,9 @@
 	 if [ "$CONFIG_FB_ATY" != "n" ]; then
 	    bool '    Mach64 GX support (EXPERIMENTAL)' CONFIG_FB_ATY_GX
 	    bool '    Mach64 CT/VT/GT/LT (incl. 3D RAGE) support' CONFIG_FB_ATY_CT
+	    if [ "$CONFIG_FB_ATY_CT" != "n" ]; then
+	       bool '    Rage XL No-BIOS Init support' CONFIG_FB_ATY_XL_INIT
+	    fi
 	 fi
  	 tristate '  ATI Radeon display support (EXPERIMENTAL)' CONFIG_FB_RADEON
 	 tristate '  ATI Rage128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/aty/Makefile linux-2.4/drivers/video/aty/Makefile
--- linux-2.4-orig/drivers/video/aty/Makefile	Wed Nov 13 15:07:59 2002
+++ linux-2.4/drivers/video/aty/Makefile	Wed Dec 11 22:21:31 2002
@@ -6,6 +6,7 @@
 obj-y				:= atyfb_base.o mach64_accel.o
 obj-$(CONFIG_FB_ATY_GX)		+= mach64_gx.o
 obj-$(CONFIG_FB_ATY_CT)		+= mach64_ct.o mach64_cursor.o
+obj-$(CONFIG_FB_ATY_XL_INIT)    += xlinit.o
 obj-m				:= $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/aty/atyfb.h linux-2.4/drivers/video/aty/atyfb.h
--- linux-2.4-orig/drivers/video/aty/atyfb.h	Wed Nov 13 15:07:59 2002
+++ linux-2.4/drivers/video/aty/atyfb.h	Wed Dec 11 22:21:31 2002
@@ -43,13 +43,17 @@
     u8 pll_ref_div;
     u8 pll_gen_cntl;
     u8 mclk_fb_div;
+    u8 mclk_fb_mult;    /* 2 or 4 */
+    u8 sclk_fb_div;
     u8 pll_vclk_cntl;
     u8 vclk_post_div;
     u8 vclk_fb_div;
     u8 pll_ext_cntl;
+    u8 spll_cntl2;
     u32 dsp_config;	/* Mach64 GTB DSP */
     u32 dsp_on_off;	/* Mach64 GTB DSP */
     u8 mclk_post_div_real;
+    u8 xclk_post_div_real;
     u8 vclk_post_div_real;
 };
 
@@ -105,6 +109,7 @@
     u32 ref_clk_per;
     u32 pll_per;
     u32 mclk_per;
+    u32 xclk_per;
     u8 bus_type;
     u8 ram_type;
     u8 mem_refresh_rate;
@@ -163,6 +168,7 @@
 #define M64F_EXTRA_BRIGHT	0x00020000
 #define M64F_LT_SLEEP		0x00040000
 #define M64F_XL_DLL		0x00080000
+#define M64F_MFB_TIMES_4	0x00100000
 

     /*
@@ -197,6 +203,34 @@
 #endif
 }
 
+static inline u16 aty_ld_le16(int regindex,
+			      const struct fb_info_aty *info)
+{
+    /* Hack for bloc 1, should be cleanly optimized by compiler */
+    if (regindex >= 0x400)
+    	regindex -= 0x800;
+
+#if defined(__mc68000__)
+    return le16_to_cpu(*((volatile u16 *)(info->ati_regbase+regindex)));
+#else
+    return readw (info->ati_regbase + regindex);
+#endif
+}
+
+static inline void aty_st_le16(int regindex, u16 val,
+			       const struct fb_info_aty *info)
+{
+    /* Hack for bloc 1, should be cleanly optimized by compiler */
+    if (regindex >= 0x400)
+    	regindex -= 0x800;
+
+#if defined(__mc68000__)
+    *((volatile u16 *)(info->ati_regbase+regindex)) = cpu_to_le16(val);
+#else
+    writew (val, info->ati_regbase + regindex);
+#endif
+}
+
 static inline u8 aty_ld_8(int regindex,
 			  const struct fb_info_aty *info)
 {
@@ -236,6 +270,19 @@
     return res;
 }
 
+/*
+ * CT family only.
+ */
+static inline void aty_st_pll(int offset, u8 val,
+			      const struct fb_info_aty *info)
+{
+    /* write addr byte */
+    aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
+    /* write the register value */
+    aty_st_8(CLOCK_CNTL + 2, val, info);
+    aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
+}
+
 
     /*
      *  DAC operations
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/aty/atyfb_base.c linux-2.4/drivers/video/aty/atyfb_base.c
--- linux-2.4-orig/drivers/video/aty/atyfb_base.c	Wed Nov 13 15:07:59 2002
+++ linux-2.4/drivers/video/aty/atyfb_base.c	Wed Dec 11 23:47:00 2002
@@ -225,6 +225,9 @@
 #ifndef MODULE
 int atyfb_setup(char*);
 #endif
+#ifdef CONFIG_FB_ATY_XL_INIT
+extern int atyfb_xl_init(struct fb_info_aty *info);
+#endif
 
 static int currcon = 0;
 
@@ -252,6 +255,7 @@
 static u32 default_vram __initdata = 0;
 static int default_pll __initdata = 0;
 static int default_mclk __initdata = 0;
+static int default_xclk __initdata = 0;
 
 #ifndef MODULE
 static char *mode_option __initdata = NULL;
@@ -298,6 +302,8 @@
 static char m64n_gtc_pp[] __initdata = "3D RAGE PRO (PQFP, PCI)";
 static char m64n_gtc_ppl[] __initdata = "3D RAGE PRO (PQFP, PCI, limited 3D)";
 static char m64n_xl[] __initdata = "3D RAGE (XL)";
+static char m64n_xl_33[] __initdata = "3D RAGE (XL PCI-33MHz)";
+static char m64n_xl_66[] __initdata = "3D RAGE (XL PCI-66MHz)";
 static char m64n_ltp_a[] __initdata = "3D RAGE LT PRO (AGP)";
 static char m64n_ltp_p[] __initdata = "3D RAGE LT PRO (PCI)";
 static char m64n_mob_p[] __initdata = "3D RAGE Mobility (PCI)";
@@ -308,59 +314,61 @@
     u16 pci_id, chip_type;
     u8 rev_mask, rev_val;
     const char *name;
-    int pll, mclk;
+    int pll, mclk, xclk;
     u32 features;
 } aty_chips[] __initdata = {
 #ifdef CONFIG_FB_ATY_GX
     /* Mach64 GX */
-    { 0x4758, 0x00d7, 0x00, 0x00, m64n_gx,      135,  50, M64F_GX },
-    { 0x4358, 0x0057, 0x00, 0x00, m64n_cx,      135,  50, M64F_GX },
+    { 0x4758, 0x00d7, 0x00, 0x00, m64n_gx,      135,  50, 50, M64F_GX },
+    { 0x4358, 0x0057, 0x00, 0x00, m64n_cx,      135,  50, 50, M64F_GX },
 #endif /* CONFIG_FB_ATY_GX */
 
 #ifdef CONFIG_FB_ATY_CT
     /* Mach64 CT */
-    { 0x4354, 0x4354, 0x00, 0x00, m64n_ct,      135,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
-    { 0x4554, 0x4554, 0x00, 0x00, m64n_et,      135,  60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
+    { 0x4354, 0x4354, 0x00, 0x00, m64n_ct,      135,  60, 60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
+    { 0x4554, 0x4554, 0x00, 0x00, m64n_et,      135,  60, 60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO },
 
     /* Mach64 VT */
-    { 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3,    170,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 },
-    { 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4,    200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV },
-    { 0x5654, 0x5654, 0x00, 0x00, m64n_vtb,     200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 },
-    { 0x5655, 0x5655, 0x00, 0x00, m64n_vtb,     200,  67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL },
-    { 0x5656, 0x5656, 0x00, 0x00, m64n_vt4,     230,  83, M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP },
+    { 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3,    170,  67, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 },
+    { 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4,    200,  67, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV },
+    { 0x5654, 0x5654, 0x00, 0x00, m64n_vtb,     200,  67, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 },
+    { 0x5655, 0x5655, 0x00, 0x00, m64n_vtb,     200,  67, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL },
+    { 0x5656, 0x5656, 0x00, 0x00, m64n_vt4,     230,  83, 83, M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP },
 
     /* Mach64 GT (3D RAGE) */
-    { 0x4754, 0x4754, 0x07, 0x00, m64n_gt,      135,  63, M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_EXTRA_BRIGHT },
-    { 0x4754, 0x4754, 0x07, 0x01, m64n_gt,      170,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4754, 0x4754, 0x07, 0x02, m64n_gt,      200,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4755, 0x4755, 0x00, 0x00, m64n_gtb,     200,  67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a,   230,  83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4754, 0x4754, 0x07, 0x00, m64n_gt,      135,  63, 63, M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_EXTRA_BRIGHT },
+    { 0x4754, 0x4754, 0x07, 0x01, m64n_gt,      170,  67, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4754, 0x4754, 0x07, 0x02, m64n_gt,      200,  67, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4755, 0x4755, 0x00, 0x00, m64n_gtb,     200,  67, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p,   230,  83, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a,   230,  83, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a,   230,  83, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
 
     /* Mach64 LT */
-    { 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt,      135,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP },
-    { 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg,     230,  63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_LT_SLEEP | M64F_G3_PB_1024x768 },
+    { 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt,      135,  63, 63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP },
+    { 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg,     230,  63, 63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_LT_SLEEP | M64F_G3_PB_1024x768 },
 
     /* Mach64 GTC (3D RAGE PRO) */
-    { 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE },
-    { 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp,  230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-    { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
-
-    /* 3D RAGE XL */
-    { 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL },
+    { 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba,  230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp,  230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE },
+    { 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp,  230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+    { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT },
+
+    /* 3D RAGE XL PCI-66/BGA */
+    { 0x474f, 0x474f, 0x00, 0x00, m64n_xl_66, 230, 83, 63, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL | M64F_MFB_TIMES_4 },
+    /* 3D RAGE XL PCI-33/BGA */
+    { 0x4752, 0x4752, 0x00, 0x00, m64n_xl_33, 230, 83, 63, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL | M64F_MFB_TIMES_4 },
 
     /* Mach64 LT PRO */
-    { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
-    { 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
-    { 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
-    { 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p,   230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
+    { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a,   230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
+    { 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p,   230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
+    { 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p,   230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 },
+    { 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p,   230, 100, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP },
 
     /* 3D RAGE Mobility */
-    { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p,   230,  50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
-    { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a,   230,  50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
+    { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p,   230,  50, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
+    { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a,   230,  50, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },
 #endif /* CONFIG_FB_ATY_CT */
 };
 
@@ -777,7 +785,7 @@
     } else {
 	i = aty_ld_le32(MEM_CNTL, info) & 0xf00fffff;
 	if (!M64_HAS(MAGIC_POSTDIV))
-	    i |= info->mem_refresh_rate << 20;
+		i |= info->mem_refresh_rate << 20;
 	switch (par->crtc.bpp) {
 	    case 8:
 	    case 24:
@@ -1249,7 +1257,10 @@
     u32 ref_clk_per;
     u8 pll_ref_div;
     u8 mclk_fb_div;
+    u8 sclk_fb_div;
     u8 mclk_post_div;		/* 1,2,3,4,8 */
+    u8 mclk_fb_mult;            /* 2 or 4 */
+    u8 xclk_post_div;		/* 1,2,3,4,8 */
     u8 vclk_fb_div;
     u8 vclk_post_div;		/* 1,2,3,4,6,8,12 */
     u32 dsp_xclks_per_row;	/* 0-16383 */
@@ -1302,14 +1313,17 @@
 	    clk.ref_clk_per = info->ref_clk_per;
 	    clk.pll_ref_div = pll->ct.pll_ref_div;
 	    clk.mclk_fb_div = pll->ct.mclk_fb_div;
+	    clk.sclk_fb_div = pll->ct.sclk_fb_div;
 	    clk.mclk_post_div = pll->ct.mclk_post_div_real;
+	    clk.mclk_fb_mult = pll->ct.mclk_fb_mult;
+	    clk.xclk_post_div = pll->ct.xclk_post_div_real;
 	    clk.vclk_fb_div = pll->ct.vclk_fb_div;
 	    clk.vclk_post_div = pll->ct.vclk_post_div_real;
 	    clk.dsp_xclks_per_row = dsp_config & 0x3fff;
 	    clk.dsp_loop_latency = (dsp_config>>16) & 0xf;
 	    clk.dsp_precision = (dsp_config>>20) & 7;
-	    clk.dsp_on = dsp_on_off & 0x7ff;
-	    clk.dsp_off = (dsp_on_off>>16) & 0x7ff;
+	    clk.dsp_off = dsp_on_off & 0x7ff;
+	    clk.dsp_on = (dsp_on_off>>16) & 0x7ff;
 	    if (copy_to_user((struct atyclk *)arg, &clk, sizeof(clk)))
 		    return -EFAULT;
 	} else
@@ -1324,14 +1338,17 @@
 	    info->ref_clk_per = clk.ref_clk_per;
 	    pll->ct.pll_ref_div = clk.pll_ref_div;
 	    pll->ct.mclk_fb_div = clk.mclk_fb_div;
+	    pll->ct.sclk_fb_div = clk.sclk_fb_div;
 	    pll->ct.mclk_post_div_real = clk.mclk_post_div;
+	    pll->ct.mclk_fb_mult = clk.mclk_fb_mult;
+	    pll->ct.xclk_post_div_real = clk.xclk_post_div;
 	    pll->ct.vclk_fb_div = clk.vclk_fb_div;
 	    pll->ct.vclk_post_div_real = clk.vclk_post_div;
 	    pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) |
 				 ((clk.dsp_loop_latency & 0xf)<<16) |
 				 ((clk.dsp_precision & 7)<<20);
-	    pll->ct.dsp_on_off = (clk.dsp_on & 0x7ff) |
-				 ((clk.dsp_off & 0x7ff)<<16);
+	    pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) |
+				 ((clk.dsp_on & 0x7ff)<<16);
 	    aty_calc_pll_ct(info, &pll->ct);
 	    aty_set_pll_ct(info, pll);
 	} else
@@ -1371,6 +1388,7 @@
 	unsigned long off;
 	int i;
 
+	printk("aty_mmap\n");
 	if (!fb->mmap_map)
 		return -ENXIO;
 
@@ -1416,9 +1434,14 @@
 		pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
 		pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
 
+		printk("calling remap_page_range: start %x offset %x\n",
+				vma->vm_start + page, map_offset);
 		if (remap_page_range(vma->vm_start + page, map_offset,
-				     map_size, vma->vm_page_prot))
+				     map_size, vma->vm_page_prot)) {
+			printk("remap failed\n");
 			return -EAGAIN;
+		}
+		printk("remap done\n");
 
 		page += map_size;
 	}
@@ -1751,6 +1774,36 @@
 #endif /* CONFIG_PMAC_BACKLIGHT */
 

+static void __init aty_calc_mem_refresh(struct fb_info_aty *info,
+					u16 id,
+					int xclk)
+{
+	int i, size;
+	const int ragepro_tbl[] = {
+		44, 50, 55, 66, 75, 80, 100
+	};
+	const int ragexl_tbl[] = {
+		50, 66, 75, 83, 90, 95, 100, 105,
+		110, 115, 120, 125, 133, 143, 166
+	};
+	const int *refresh_tbl;
+
+	if (IS_XL(id)) {
+		refresh_tbl = ragexl_tbl;
+		size = sizeof(ragexl_tbl)/sizeof(int);
+	} else {
+		refresh_tbl = ragepro_tbl;
+		size = sizeof(ragepro_tbl)/sizeof(int);
+	}
+	
+	for (i=0; i < size; i++) {
+		if (xclk < refresh_tbl[i])
+			break;
+	}
+	
+	info->mem_refresh_rate = i;
+}
+
 
     /*
      *  Initialisation
@@ -1768,12 +1821,12 @@
     u16 type;
     u8 rev;
     const char *chipname = NULL, *ramname = NULL, *xtal;
-    int pll, mclk, gtb_memsize;
+    int pll, mclk, xclk, gtb_memsize;
 #if defined(CONFIG_PPC)
     int sense;
 #endif
     u8 pll_ref_div;
-
+    
     info->aty_cmap_regs = (struct aty_cmap_regs *)(info->ati_regbase+0xc0);
     chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
     type = chip_id & CFG_CHIP_TYPE;
@@ -1784,6 +1837,7 @@
 	    chipname = aty_chips[j].name;
 	    pll = aty_chips[j].pll;
 	    mclk = aty_chips[j].mclk;
+	    xclk = aty_chips[j].xclk;
 	    info->features = aty_chips[j].features;
 	    goto found;
 	}
@@ -1854,17 +1908,39 @@
 	}
     }
 #endif /* CONFIG_FB_ATY_GX */
+
 #ifdef CONFIG_FB_ATY_CT
     if (M64_HAS(INTEGRATED)) {
-	info->bus_type = PCI;
-	info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
-	ramname = aty_ct_ram[info->ram_type];
-	info->dac_ops = &aty_dac_ct;
-	info->pll_ops = &aty_pll_ct;
 	/* for many chips, the mclk is 67 MHz for SDRAM, 63 MHz otherwise */
 	if (mclk == 67 && info->ram_type < SDRAM)
 	    mclk = 63;
     }
+#endif
+    
+    if (default_pll)
+	pll = default_pll;
+    if (default_mclk)
+	mclk = default_mclk;
+    if (default_xclk)
+	xclk = default_xclk;
+
+    aty_calc_mem_refresh(info, type, xclk);
+    info->pll_per = 1000000/pll;
+    info->mclk_per = 1000000/mclk;
+    info->xclk_per = 1000000/xclk;
+
+#ifdef CONFIG_FB_ATY_CT
+    if (M64_HAS(INTEGRATED)) {
+	info->dac_ops = &aty_dac_ct;
+	info->pll_ops = &aty_pll_ct;
+	info->bus_type = PCI;
+#ifdef CONFIG_FB_ATY_XL_INIT
+	if (IS_XL(type))
+		atyfb_xl_init(info);
+#endif
+	info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
+	ramname = aty_ct_ram[info->ram_type];
+    }
 #endif /* CONFIG_FB_ATY_CT */
 
     info->ref_clk_per = 1000000000000ULL/14318180;
@@ -1954,33 +2030,11 @@
 	    i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
 	aty_st_le32(MEM_CNTL, i, info);
     }
-    if (default_pll)
-	pll = default_pll;
-    if (default_mclk)
-	mclk = default_mclk;
 
-    printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK\n",
+    printk("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d Mhz XCLK\n",
     	   info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
-    	   info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll, mclk);
-
-    if (mclk < 44)
-	info->mem_refresh_rate = 0;	/* 000 = 10 Mhz - 43 Mhz */
-    else if (mclk < 50)
-	info->mem_refresh_rate = 1;	/* 001 = 44 Mhz - 49 Mhz */
-    else if (mclk < 55)
-	info->mem_refresh_rate = 2;	/* 010 = 50 Mhz - 54 Mhz */
-    else if (mclk < 66)
-	info->mem_refresh_rate = 3;	/* 011 = 55 Mhz - 65 Mhz */
-    else if (mclk < 75)
-	info->mem_refresh_rate = 4;	/* 100 = 66 Mhz - 74 Mhz */
-    else if (mclk < 80)
-	info->mem_refresh_rate = 5;	/* 101 = 75 Mhz - 79 Mhz */
-    else if (mclk < 100)
-	info->mem_refresh_rate = 6;	/* 110 = 80 Mhz - 100 Mhz */
-    else
-	info->mem_refresh_rate = 7;	/* 111 = 100 Mhz and above */
-    info->pll_per = 1000000/pll;
-    info->mclk_per = 1000000/mclk;
+    	   info->total_vram == 0x80000 ? 'K' : 'M', ramname, xtal, pll,
+	   mclk, xclk);
 
 #ifdef DEBUG
     if (M64_HAS(INTEGRATED)) {
@@ -2280,7 +2334,7 @@
 		j++;
 	    }
 
-	    if (pdev->device != XL_CHIP_ID) {
+	    if (!IS_XL(pdev->device)) {
 		    /*
 		     * Fix PROMs idea of MEM_CNTL settings...
 		     */
@@ -2390,7 +2444,7 @@
 		 *
 		 * where R is XTALIN (= 14318 or 29498 kHz).
 		 */
-		if (pdev->device == XL_CHIP_ID)
+		if (IS_XL(pdev->device))
 			R = 29498;
 		else
 			R = 14318;
@@ -2580,6 +2634,8 @@
 		default_pll = simple_strtoul(this_opt+4, NULL, 0);
 	else if (!strncmp(this_opt, "mclk:", 5))
 		default_mclk = simple_strtoul(this_opt+5, NULL, 0);
+	else if (!strncmp(this_opt, "xclk:", 5))
+		default_xclk = simple_strtoul(this_opt+5, NULL, 0);
 #ifdef CONFIG_PPC
 	else if (!strncmp(this_opt, "vmode:", 6)) {
 	    unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/aty/mach64.h linux-2.4/drivers/video/aty/mach64.h
--- linux-2.4-orig/drivers/video/aty/mach64.h	Thu Aug 23 20:38:49 2001
+++ linux-2.4/drivers/video/aty/mach64.h	Wed Dec 11 22:21:31 2002
@@ -849,7 +849,18 @@
 #define LI_CHIP_ID	0x4c49	/* RAGE LT PRO */
 #define LP_CHIP_ID	0x4c50	/* RAGE LT PRO */
 #define LT_CHIP_ID	0x4c54	/* RAGE LT */
-#define XL_CHIP_ID	0x4752	/* RAGE (XL) */
+
+#define GR_CHIP_ID	0x4752	/* RAGE XL, BGA, PCI33 */
+#define GS_CHIP_ID	0x4753	/* RAGE XL, PQFP, PCI33 */
+#define GM_CHIP_ID	0x474d	/* RAGE XL, BGA, AGP 1x,2x */
+#define GN_CHIP_ID	0x474e	/* RAGE XL, PQFP,AGP 1x,2x */
+#define GO_CHIP_ID	0x474f	/* RAGE XL, BGA, PCI66 */
+#define GL_CHIP_ID	0x474c	/* RAGE XL, PQFP, PCI66 */
+
+#define IS_XL(id) ((id)==GR_CHIP_ID || (id)==GS_CHIP_ID || \
+                   (id)==GM_CHIP_ID || (id)==GN_CHIP_ID || \
+                   (id)==GO_CHIP_ID || (id)==GL_CHIP_ID)
+
 #define GT_CHIP_ID	0x4754	/* RAGE (GT) */
 #define GU_CHIP_ID	0x4755	/* RAGE II/II+ (GTB) */
 #define GV_CHIP_ID	0x4756	/* RAGE IIC, PCI */
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/aty/mach64_ct.c linux-2.4/drivers/video/aty/mach64_ct.c
--- linux-2.4-orig/drivers/video/aty/mach64_ct.c	Thu Aug 23 20:38:49 2001
+++ linux-2.4/drivers/video/aty/mach64_ct.c	Wed Dec 11 22:21:31 2002
@@ -4,6 +4,7 @@
  */
 
 #include <linux/fb.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 
@@ -12,15 +13,14 @@
 #include "mach64.h"
 #include "atyfb.h"
 
+#undef DEBUG
 
 /* FIXME: remove the FAIL definition */
 #define FAIL(x) do { printk(x "\n"); return -EINVAL; } while (0)
 
-static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
-
 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
 			    struct pll_ct *pll);
-static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
+static int aty_dsp_gt(const struct fb_info_aty *info, u32 bpp,
 		      struct pll_ct *pll);
 static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
 			     u8 bpp, union aty_pll *pll);
@@ -28,34 +28,30 @@
 			     const union aty_pll *pll);
 

-
-static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
-{
-    /* write addr byte */
-    aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN, info);
-    /* write the register value */
-    aty_st_8(CLOCK_CNTL + 2, val, info);
-    aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
-}
-
-
 /* ------------------------------------------------------------------------- */
 
     /*
      *  PLL programming (Mach64 CT family)
      */
-
-static int aty_dsp_gt(const struct fb_info_aty *info, u8 bpp,
+static int aty_dsp_gt(const struct fb_info_aty *info, u32 bpp,
 		      struct pll_ct *pll)
 {
     u32 dsp_xclks_per_row, dsp_loop_latency, dsp_precision, dsp_off, dsp_on;
-    u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size, page_size;
+    u32 xclks_per_row, fifo_off, fifo_on, y, fifo_size;
+    u32 memcntl, n, t_pfc, t_rp, t_ras, t_rcd, t_crd, t_rcc, t_lat;
+
+#ifdef DEBUG
+    printk(__FUNCTION__ ": mclk_fb_mult=%d\n", pll->mclk_fb_mult);
+#endif
+    
+    /* (64*xclk/vclk/bpp)<<11 = xclocks_per_row<<11 */
+    xclks_per_row = ((u32)pll->mclk_fb_mult * (u32)pll->mclk_fb_div *
+		     (u32)pll->vclk_post_div_real * 64) << 11;
+    xclks_per_row /=
+	    (2 * (u32)pll->vclk_fb_div * (u32)pll->xclk_post_div_real * bpp);
 
-    /* xclocks_per_row<<11 */
-    xclks_per_row = (pll->mclk_fb_div*pll->vclk_post_div_real*64<<11)/
-		    (pll->vclk_fb_div*pll->mclk_post_div_real*bpp);
     if (xclks_per_row < (1<<11))
-	FAIL("Dotclock to high");
+	FAIL("Dotclock too high");
     if (M64_HAS(FIFO_24)) {
 	fifo_size = 24;
 	dsp_loop_latency = 0;
@@ -70,35 +66,54 @@
 	dsp_precision++;
     }
     dsp_precision -= 5;
+
     /* fifo_off<<6 */
-    fifo_off = ((xclks_per_row*(fifo_size-1))>>5)+(3<<6);
+    fifo_off = ((xclks_per_row*(fifo_size-1))>>5); // + (3<<6);
 
     if (info->total_vram > 1*1024*1024) {
-	if (info->ram_type >= SDRAM) {
+	switch (info->ram_type) {
+	case WRAM:
+	    /* >1 MB WRAM */
+	    dsp_loop_latency += 9;
+	    n = 4;
+	    break;
+	case SDRAM:
+	case SGRAM:
 	    /* >1 MB SDRAM */
 	    dsp_loop_latency += 8;
-	    page_size = 8;
-	} else {
+	    n = 2;
+	    break;
+	default:
 	    /* >1 MB DRAM */
 	    dsp_loop_latency += 6;
-	    page_size = 9;
+	    n = 3;
+	    break;
 	}
     } else {
 	if (info->ram_type >= SDRAM) {
 	    /* <2 MB SDRAM */
 	    dsp_loop_latency += 9;
-	    page_size = 10;
+	    n = 2;
 	} else {
 	    /* <2 MB DRAM */
 	    dsp_loop_latency += 8;
-	    page_size = 10;
+	    n = 3;
 	}
     }
+
+    memcntl = aty_ld_le32(MEM_CNTL, info);
+    t_rcd = ((memcntl >> 10) & 0x03) + 1;
+    t_crd = ((memcntl >> 12) & 0x01);
+    t_rp  = ((memcntl >>  8) & 0x03) + 1;
+    t_ras = ((memcntl >> 16) & 0x07) + 1;
+    t_lat =  (memcntl >>  4) & 0x03;
+    
+    t_pfc = t_rp + t_rcd + t_crd;
+    
+    t_rcc = max(t_rp + t_ras, t_pfc + n);
+    
     /* fifo_on<<6 */
-    if (xclks_per_row >= (page_size<<11))
-	fifo_on = ((2*page_size+1)<<6)+(xclks_per_row>>5);
-    else
-	fifo_on = (3*page_size+2)<<6;
+    fifo_on = (2 * t_rcc + t_pfc + n - 1) << 6;
 
     dsp_xclks_per_row = xclks_per_row>>dsp_precision;
     dsp_on = fifo_on>>dsp_precision;
@@ -107,20 +122,27 @@
     pll->dsp_config = (dsp_xclks_per_row & 0x3fff) |
 		      ((dsp_loop_latency & 0xf)<<16) |
 		      ((dsp_precision & 7)<<20);
-    pll->dsp_on_off = (dsp_on & 0x7ff) | ((dsp_off & 0x7ff)<<16);
+    pll->dsp_on_off = (dsp_off & 0x7ff) | ((dsp_on & 0x7ff)<<16);
     return 0;
 }
 
+
 static int aty_valid_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
 			    struct pll_ct *pll)
 {
+#ifdef DEBUG
+    int pllmclk, pllsclk;
+#endif
     u32 q, x;			/* x is a workaround for sparc64-linux-gcc */
     x = x;			/* x is a workaround for sparc64-linux-gcc */
-
+    
     pll->pll_ref_div = info->pll_per*2*255/info->ref_clk_per;
-
+    
     /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
-    q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per;	/* actually 8*q */
+
+    /* actually 8*q */
+    q = info->ref_clk_per*pll->pll_ref_div*4/info->mclk_per;
+
     if (q < 16*8 || q > 255*8)
 	FAIL("mclk out of range");
     else if (q < 32*8)
@@ -131,8 +153,40 @@
 	pll->mclk_post_div_real = 2;
     else
 	pll->mclk_post_div_real = 1;
-    pll->mclk_fb_div = q*pll->mclk_post_div_real/8;
+    pll->sclk_fb_div = q*pll->mclk_post_div_real/8;
+    
+#ifdef DEBUG
+    pllsclk = (1000000 * 2 * pll->sclk_fb_div) /
+	    (info->ref_clk_per * pll->pll_ref_div);
+    printk(__FUNCTION__ ": pllsclk=%d MHz, mclk=%d MHz\n",
+	   pllsclk, pllsclk / pll->mclk_post_div_real);
+#endif
+    
+    pll->mclk_fb_mult = M64_HAS(MFB_TIMES_4) ? 4 : 2;
+
+    /* actually 8*q */
+    q = info->ref_clk_per * pll->pll_ref_div * 8 /
+	    (pll->mclk_fb_mult * info->xclk_per);
 
+    if (q < 16*8 || q > 255*8)
+	FAIL("mclk out of range");
+    else if (q < 32*8)
+	pll->xclk_post_div_real = 8;
+    else if (q < 64*8)
+	pll->xclk_post_div_real = 4;
+    else if (q < 128*8)
+	pll->xclk_post_div_real = 2;
+    else
+	pll->xclk_post_div_real = 1;
+    pll->mclk_fb_div = q*pll->xclk_post_div_real/8;
+    
+#ifdef DEBUG
+    pllmclk = (1000000 * pll->mclk_fb_mult * pll->mclk_fb_div) /
+	    (info->ref_clk_per * pll->pll_ref_div);
+    printk(__FUNCTION__ ": pllmclk=%d MHz, xclk=%d MHz\n",
+	   pllmclk, pllmclk / pll->xclk_post_div_real);
+#endif
+    
     /* FIXME: use the VTB/GTB /{3,6,12} post dividers if they're better suited */
     q = info->ref_clk_per*pll->pll_ref_div*4/vclk_per;	/* actually 8*q */
     if (q < 16*8 || q > 255*8)
@@ -151,13 +205,14 @@
 
 void aty_calc_pll_ct(const struct fb_info_aty *info, struct pll_ct *pll)
 {
+    u8 xpostdiv = 0;
     u8 mpostdiv = 0;
     u8 vpostdiv = 0;
-
+    
     if (M64_HAS(SDRAM_MAGIC_PLL) && (info->ram_type >= SDRAM))
-	pll->pll_gen_cntl = 0x04;
+	    pll->pll_gen_cntl = 0x64; /* mclk = sclk */
     else
-	pll->pll_gen_cntl = 0x84;
+	pll->pll_gen_cntl = 0xe4; /* mclk = sclk */
 
     switch (pll->mclk_post_div_real) {
 	case 1:
@@ -166,9 +221,6 @@
 	case 2:
 	    mpostdiv = 1;
 	    break;
-	case 3:
-	    mpostdiv = 4;
-	    break;
 	case 4:
 	    mpostdiv = 2;
 	    break;
@@ -176,12 +228,34 @@
 	    mpostdiv = 3;
 	    break;
     }
-    pll->pll_gen_cntl |= mpostdiv<<4;	/* mclk */
+
+    pll->spll_cntl2 = mpostdiv << 4; /* sclk == pllsclk / mpostdiv */
+    
+    switch (pll->xclk_post_div_real) {
+	case 1:
+	    xpostdiv = 0;
+	    break;
+	case 2:
+	    xpostdiv = 1;
+	    break;
+	case 3:
+	    xpostdiv = 4;
+	    break;
+	case 4:
+	    xpostdiv = 2;
+	    break;
+	case 8:
+	    xpostdiv = 3;
+	    break;
+    }
 
     if (M64_HAS(MAGIC_POSTDIV))
 	pll->pll_ext_cntl = 0;
     else
-    	pll->pll_ext_cntl = mpostdiv;	/* xclk == mclk */
+	pll->pll_ext_cntl = xpostdiv;	/* xclk == pllmclk / xpostdiv */
+
+    if (pll->mclk_fb_mult == 4)
+	    pll->pll_ext_cntl |= 0x08;
 
     switch (pll->vclk_post_div_real) {
 	case 2:
@@ -234,24 +308,54 @@
 
 void aty_set_pll_ct(const struct fb_info_aty *info, const union aty_pll *pll)
 {
+#ifdef DEBUG
+    printk(__FUNCTION__ ": about to program:\n"
+	   "refdiv=%d, extcntl=0x%02x, mfbdiv=%d\n"
+	   "spllcntl2=0x%02x, sfbdiv=%d, gencntl=0x%02x\n"
+	   "vclkcntl=0x%02x, vpostdiv=0x%02x, vfbdiv=%d\n"
+	   "clocksel=%d\n",
+	   pll->ct.pll_ref_div, pll->ct.pll_ext_cntl,
+	   pll->ct.mclk_fb_div, pll->ct.spll_cntl2,
+	   pll->ct.sclk_fb_div, pll->ct.pll_gen_cntl,
+	   pll->ct.pll_vclk_cntl, pll->ct.vclk_post_div,
+	   pll->ct.vclk_fb_div, aty_ld_le32(CLOCK_CNTL, info) & 0x03);
+#endif
+
     aty_st_pll(PLL_REF_DIV, pll->ct.pll_ref_div, info);
+
+    aty_st_pll(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, info);
+    aty_st_pll(MCLK_FB_DIV, pll->ct.mclk_fb_div, info); // for XCLK
+    
+    aty_st_pll(SPLL_CNTL2, pll->ct.spll_cntl2, info);
+    aty_st_pll(SCLK_FB_DIV, pll->ct.sclk_fb_div, info); // for MCLK
+
     aty_st_pll(PLL_GEN_CNTL, pll->ct.pll_gen_cntl, info);
-    aty_st_pll(MCLK_FB_DIV, pll->ct.mclk_fb_div, info);
+    
+    aty_st_pll(EXT_VPLL_CNTL, 0, info);
     aty_st_pll(PLL_VCLK_CNTL, pll->ct.pll_vclk_cntl, info);
     aty_st_pll(VCLK_POST_DIV, pll->ct.vclk_post_div, info);
     aty_st_pll(VCLK0_FB_DIV, pll->ct.vclk_fb_div, info);
-    aty_st_pll(PLL_EXT_CNTL, pll->ct.pll_ext_cntl, info);
 
     if (M64_HAS(GTB_DSP)) {
+	u8 dll_cntl;
+
 	if (M64_HAS(XL_DLL))
-	    aty_st_pll(DLL_CNTL, 0x80, info);
+	    dll_cntl = 0x80;
 	else if (info->ram_type >= SDRAM)
-	    aty_st_pll(DLL_CNTL, 0xa6, info);
+	    dll_cntl = 0xa6;
 	else
-	    aty_st_pll(DLL_CNTL, 0xa0, info);
+	    dll_cntl = 0xa0;
+	aty_st_pll(DLL_CNTL, dll_cntl, info);
 	aty_st_pll(VFC_CNTL, 0x1b, info);
 	aty_st_le32(DSP_CONFIG, pll->ct.dsp_config, info);
 	aty_st_le32(DSP_ON_OFF, pll->ct.dsp_on_off, info);
+
+	mdelay(10);
+	aty_st_pll(DLL_CNTL, dll_cntl, info);
+	mdelay(10);
+	aty_st_pll(DLL_CNTL, dll_cntl | 0x40, info);
+	mdelay(10);
+	aty_st_pll(DLL_CNTL, dll_cntl & ~0x40, info);
     }
 }
 
diff -Naur --exclude=CVS linux-2.4-orig/drivers/video/aty/xlinit.c linux-2.4/drivers/video/aty/xlinit.c
--- linux-2.4-orig/drivers/video/aty/xlinit.c	Wed Dec 31 16:00:00 1969
+++ linux-2.4/drivers/video/aty/xlinit.c	Wed Dec 11 22:21:31 2002
@@ -0,0 +1,374 @@
+/*
+ *  ATI Rage XL Initialization. Support for Xpert98 and Victoria
+ *  PCI cards.
+ *
+ *  Copyright (C) 2002 MontaVista Software Inc.
+ *  Author: MontaVista Software, Inc.
+ *         	stevel@mvista.com or source@mvista.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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the  GNU General Public License along
+ *  with this program; if not, write  to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h> 
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/selection.h>
+#include <linux/console.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/vt_kern.h>
+#include <linux/kd.h> 
+#include <asm/io.h>
+#include <video/fbcon.h>
+#include "mach64.h"
+#include "atyfb.h"
+
+#define MPLL_GAIN       0xad
+#define VPLL_GAIN       0xd5
+
+enum {
+	VICTORIA = 0,
+	XPERT98,
+	NUM_XL_CARDS
+};
+
+extern const struct aty_pll_ops aty_pll_ct;
+
+#define DEFAULT_CARD XPERT98
+static int xl_card = DEFAULT_CARD;
+
+static const struct xl_card_cfg_t {
+	int ref_crystal; // 10^4 Hz
+	int mem_type;
+	int mem_size;
+	u32 mem_cntl;
+	u32 ext_mem_cntl;
+	u32 mem_addr_config;
+	u32 bus_cntl;
+	u32 dac_cntl;
+	u32 hw_debug;
+	u32 custom_macro_cntl;
+	u8  dll2_cntl;
+	u8  pll_yclk_cntl;
+} card_cfg[NUM_XL_CARDS] = {
+	// VICTORIA
+	{	2700, SDRAM, 0x800000,
+		0x10757A3B, 0x64000C81, 0x00110202, 0x7b33A040,
+		0x82010102, 0x48803800, 0x005E0179,
+		0x50, 0x25
+	},
+	// XPERT98
+	{	1432,  WRAM, 0x800000,
+		0x00165A2B, 0xE0000CF1, 0x00200213, 0x7333A001,
+		0x8000000A, 0x48833800, 0x007F0779,
+		0x10, 0x19
+	}
+};
+	  
+typedef struct {
+	u8 lcd_reg;
+	u32 val;
+} lcd_tbl_t;
+
+static const lcd_tbl_t lcd_tbl[] = {
+	{ 0x01,	0x000520C0 },
+	{ 0x08,	0x02000408 },
+	{ 0x03,	0x00000F00 },
+	{ 0x00,	0x00000000 },
+	{ 0x02,	0x00000000 },
+	{ 0x04,	0x00000000 },
+	{ 0x05,	0x00000000 },
+	{ 0x06,	0x00000000 },
+	{ 0x33,	0x00000000 },
+	{ 0x34,	0x00000000 },
+	{ 0x35,	0x00000000 },
+	{ 0x36,	0x00000000 },
+	{ 0x37,	0x00000000 }
+};
+
+static inline u32 aty_ld_lcd(u8 lcd_reg, struct fb_info_aty *info)
+{
+	aty_st_8(LCD_INDEX, lcd_reg, info);
+	return aty_ld_le32(LCD_DATA, info);
+}
+
+static inline void aty_st_lcd(u8 lcd_reg, u32 val,
+			      struct fb_info_aty *info)
+{
+	aty_st_8(LCD_INDEX, lcd_reg, info);
+	aty_st_le32(LCD_DATA, val, info);
+}
+
+static void reset_gui(struct fb_info_aty *info)
+{
+	aty_st_8(GEN_TEST_CNTL+1, 0x01, info);
+	aty_st_8(GEN_TEST_CNTL+1, 0x00, info);
+	aty_st_8(GEN_TEST_CNTL+1, 0x02, info);
+	mdelay(5);
+}
+
+
+static void reset_sdram(struct fb_info_aty *info)
+{
+	u8 temp;
+
+	temp = aty_ld_8(EXT_MEM_CNTL, info);
+	temp |= 0x02;
+	aty_st_8(EXT_MEM_CNTL, temp, info); // MEM_SDRAM_RESET = 1b
+	temp |= 0x08;
+	aty_st_8(EXT_MEM_CNTL, temp, info); // MEM_CYC_TEST    = 10b
+	temp |= 0x0c;
+	aty_st_8(EXT_MEM_CNTL, temp, info); // MEM_CYC_TEST    = 11b
+	mdelay(5);
+	temp &= 0xf3;
+	aty_st_8(EXT_MEM_CNTL, temp, info); // MEM_CYC_TEST    = 00b
+	temp &= 0xfd;
+	aty_st_8(EXT_MEM_CNTL, temp, info); // MEM_SDRAM_REST  = 0b
+	mdelay(5);
+}
+
+static void init_dll(struct fb_info_aty *info)
+{
+	// enable DLL
+	aty_st_pll(PLL_GEN_CNTL,
+		   aty_ld_pll(PLL_GEN_CNTL, info) & 0x7f,
+		   info);
+
+	// reset DLL
+	aty_st_pll(DLL_CNTL, 0x82, info);
+	aty_st_pll(DLL_CNTL, 0xE2, info);
+	mdelay(5);
+	aty_st_pll(DLL_CNTL, 0x82, info);
+	mdelay(6);
+}
+
+static void reset_clocks(struct fb_info_aty *info, struct pll_ct *pll,
+			 int hsync_enb)
+{
+	reset_gui(info);
+	aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info);
+	aty_st_pll(SCLK_FB_DIV, pll->sclk_fb_div, info);
+
+	mdelay(15);
+	init_dll(info);
+	aty_st_8(GEN_TEST_CNTL+1, 0x00, info);
+	mdelay(5);
+	aty_st_8(CRTC_GEN_CNTL+3, 0x04, info);
+	mdelay(6);
+	reset_sdram(info);
+	aty_st_8(CRTC_GEN_CNTL+3,
+		 hsync_enb ? 0x00 : 0x04, info);
+
+	aty_st_pll(SPLL_CNTL2, pll->spll_cntl2, info);
+	aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info);
+	aty_st_pll(PLL_VCLK_CNTL, pll->pll_vclk_cntl, info);
+}
+
+
+int atyfb_xl_init(struct fb_info_aty *info)
+{
+	int i, err;
+	u32 temp;
+	union aty_pll pll;
+	const struct xl_card_cfg_t * card = &card_cfg[xl_card];
+	
+	aty_st_8(CONFIG_STAT0, 0x85, info);
+	mdelay(10);
+
+	/*
+	 * The following needs to be set before the call
+	 * to var_to_pll() below. They'll be re-set again
+	 * to the same values in aty_init().
+	 */
+	info->ref_clk_per = 100000000UL/card->ref_crystal;
+	info->ram_type = card->mem_type;
+	info->total_vram = card->mem_size;
+	if (xl_card == VICTORIA) {
+		// the MCLK, XCLK are 120MHz on victoria card
+		info->mclk_per = 1000000/120;
+		info->xclk_per = 1000000/120;
+		info->features &= ~M64F_MFB_TIMES_4;
+	}
+	
+	/*
+	 * Calculate mclk and xclk dividers, etc. The passed
+	 * pixclock and bpp values don't matter yet, the vclk
+	 * isn't programmed until later.
+	 */
+	if ((err = aty_pll_ct.var_to_pll(info, 39726, 8, &pll)))
+		return err;
+
+	aty_st_pll(LVDS_CNTL0, 0x00, info);
+	aty_st_pll(DLL2_CNTL, card->dll2_cntl, info);
+	aty_st_pll(V2PLL_CNTL, 0x10, info);
+	aty_st_pll(MPLL_CNTL, MPLL_GAIN, info);
+	aty_st_pll(VPLL_CNTL, VPLL_GAIN, info);
+	aty_st_pll(PLL_VCLK_CNTL, 0x00, info);
+	aty_st_pll(VFC_CNTL, 0x1B, info);
+	aty_st_pll(PLL_REF_DIV, pll.ct.pll_ref_div, info);
+	aty_st_pll(PLL_EXT_CNTL, pll.ct.pll_ext_cntl, info);
+	aty_st_pll(SPLL_CNTL2, 0x03, info);
+	aty_st_pll(PLL_GEN_CNTL, 0x44, info);
+
+	reset_clocks(info, &pll.ct, 0);
+	mdelay(10);
+
+	aty_st_pll(VCLK_POST_DIV, 0x03, info);
+	aty_st_pll(VCLK0_FB_DIV, 0xDA, info);
+	aty_st_pll(VCLK_POST_DIV, 0x0F, info);
+	aty_st_pll(VCLK1_FB_DIV, 0xF5, info);
+	aty_st_pll(VCLK_POST_DIV, 0x3F, info);
+	aty_st_pll(PLL_EXT_CNTL, 0x40 | pll.ct.pll_ext_cntl, info);
+	aty_st_pll(VCLK2_FB_DIV, 0x00, info);
+	aty_st_pll(VCLK_POST_DIV, 0xFF, info);
+	aty_st_pll(PLL_EXT_CNTL, 0xC0 | pll.ct.pll_ext_cntl, info);
+	aty_st_pll(VCLK3_FB_DIV, 0x00, info);
+
+	aty_st_8(BUS_CNTL, 0x01, info);
+	aty_st_le32(BUS_CNTL, card->bus_cntl | 0x08000000, info);
+
+	aty_st_le32(CRTC_GEN_CNTL, 0x04000200, info);
+	aty_st_le16(CONFIG_STAT0, 0x0020, info);
+	aty_st_le32(MEM_CNTL, 0x10151A33, info);
+	aty_st_le32(EXT_MEM_CNTL, 0xE0000C01, info);
+	aty_st_le16(CRTC_GEN_CNTL+2, 0x0000, info);
+	aty_st_le32(DAC_CNTL, card->dac_cntl, info);
+	aty_st_le16(GEN_TEST_CNTL, 0x0100, info);
+	aty_st_le32(CUSTOM_MACRO_CNTL, 0x003C0171, info);
+	aty_st_le32(MEM_BUF_CNTL, 0x00382848, info);
+
+	aty_st_le32(HW_DEBUG, card->hw_debug, info);
+	aty_st_le16(MEM_ADDR_CONFIG, 0x0000, info);
+	aty_st_le16(GP_IO+2, 0x0000, info);
+	aty_st_le16(GEN_TEST_CNTL, 0x0000, info);
+	aty_st_le16(EXT_DAC_REGS+2, 0x0000, info);
+	aty_st_le32(CRTC_INT_CNTL, 0x00000000, info);
+	aty_st_le32(TIMER_CONFIG, 0x00000000, info);
+	aty_st_le32(0xEC, 0x00000000, info);
+	aty_st_le32(0xFC, 0x00000000, info);
+
+	for (i=0; i<sizeof(lcd_tbl)/sizeof(lcd_tbl_t); i++) {
+		aty_st_lcd(lcd_tbl[i].lcd_reg, lcd_tbl[i].val, info);
+	}
+
+	aty_st_le16(CONFIG_STAT0, 0x00A4, info);
+	mdelay(10);
+
+	aty_st_8(BUS_CNTL+1, 0xA0, info);
+	mdelay(10);
+	
+	reset_clocks(info, &pll.ct, 1);
+	mdelay(10);
+
+	// something about power management
+	aty_st_8(LCD_INDEX, 0x08, info);
+	aty_st_8(LCD_DATA, 0x0A, info);
+	aty_st_8(LCD_INDEX, 0x08, info);
+	aty_st_8(LCD_DATA+3, 0x02, info);
+	aty_st_8(LCD_INDEX, 0x08, info);
+	aty_st_8(LCD_DATA, 0x0B, info);
+	mdelay(2);
+	
+	// enable display requests, enable CRTC
+	aty_st_8(CRTC_GEN_CNTL+3, 0x02, info);
+	// disable display
+	aty_st_8(CRTC_GEN_CNTL, 0x40, info);
+	// disable display requests, disable CRTC
+	aty_st_8(CRTC_GEN_CNTL+3, 0x04, info);
+	mdelay(10);
+
+	aty_st_pll(PLL_YCLK_CNTL, 0x25, info);
+
+	aty_st_le16(CUSTOM_MACRO_CNTL, 0x0179, info);
+	aty_st_le16(CUSTOM_MACRO_CNTL+2, 0x005E, info);
+	aty_st_le16(CUSTOM_MACRO_CNTL+2, card->custom_macro_cntl>>16, info);
+	aty_st_8(CUSTOM_MACRO_CNTL+1,
+		 (card->custom_macro_cntl>>8) & 0xff, info);
+
+	aty_st_le32(MEM_ADDR_CONFIG, card->mem_addr_config, info);
+	aty_st_le32(MEM_CNTL, card->mem_cntl, info);
+	aty_st_le32(EXT_MEM_CNTL, card->ext_mem_cntl, info);
+
+	aty_st_8(CONFIG_STAT0, 0xA0 | card->mem_type, info);
+
+	aty_st_pll(PLL_YCLK_CNTL, 0x01, info);
+	mdelay(15);
+	aty_st_pll(PLL_YCLK_CNTL, card->pll_yclk_cntl, info);
+	mdelay(1);
+	
+	reset_clocks(info, &pll.ct, 0);
+	mdelay(50);
+	reset_clocks(info, &pll.ct, 0);
+	mdelay(50);
+
+	// enable extended register block
+	aty_st_8(BUS_CNTL+3, 0x7B, info);
+	mdelay(1);
+	// disable extended register block
+	aty_st_8(BUS_CNTL+3, 0x73, info);
+
+	aty_st_8(CONFIG_STAT0, 0x80 | card->mem_type, info);
+
+	// disable display requests, disable CRTC
+	aty_st_8(CRTC_GEN_CNTL+3, 0x04, info);
+	// disable mapping registers in VGA aperture
+	aty_st_8(CONFIG_CNTL, aty_ld_8(CONFIG_CNTL, info) & ~0x04, info);
+	mdelay(50);
+	// enable display requests, enable CRTC
+	aty_st_8(CRTC_GEN_CNTL+3, 0x02, info);
+
+	// make GPIO's 14,15,16 all inputs
+	aty_st_8(LCD_INDEX, 0x07, info);
+	aty_st_8(LCD_DATA+3, 0x00, info);
+
+	// enable the display
+	aty_st_8(CRTC_GEN_CNTL, 0x00, info);
+	mdelay(17);
+	// reset the memory controller
+	aty_st_8(GEN_TEST_CNTL+1, 0x02, info);
+	mdelay(15);
+	aty_st_8(GEN_TEST_CNTL+1, 0x00, info);
+	mdelay(30);
+
+	// enable extended register block
+	aty_st_8(BUS_CNTL+3,
+		 (u8)(aty_ld_8(BUS_CNTL+3, info) | 0x08),
+		 info);
+	// set FIFO size to 512 (PIO)
+	aty_st_le32(GUI_CNTL,
+		    aty_ld_le32(GUI_CNTL, info) & ~0x3,
+		    info);
+
+	// enable CRT and disable lcd
+	aty_st_8(LCD_INDEX, 0x01, info);
+	temp = aty_ld_le32(LCD_DATA, info);
+	temp = (temp | 0x01) & ~0x02;
+	aty_st_le32(LCD_DATA, temp, info);
+
+	return 0;
+}
+

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2002-12-14  4:50 Pete Popov
  0 siblings, 0 replies; 80+ messages in thread
From: Pete Popov @ 2002-12-14  4:50 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

Ralf,

Here's an updated patch for 36 bit address support to replace the patch
I sent you a couple of days ago. This one is "complete" because it takes
care of remap_page_range() as well. It has been tested with a few 36 bit
peripherals on the Alchemy boards. The remap_page_range() fixup was
needed for a RageXL PCI card on the Pb1500 PCI bus and X runs fine on
it.  The patch takes effect only if  CONFIG_64BIT_PHYS_ADDR and
CONFIG_CPU_MIPS32 are both defined.  Otherwise it's a noop. A similar
solution was tested and implemented on PPC, 2.4.x.

Pete

diff -Naur --exclude=CVS linux-2.4-orig/arch/mips/mm/Makefile linux-2.4/arch/mips/mm/Makefile
--- linux-2.4-orig/arch/mips/mm/Makefile	Mon Dec  9 16:57:46 2002
+++ linux-2.4/arch/mips/mm/Makefile	Tue Dec 10 22:14:30 2002
@@ -25,7 +25,7 @@
 obj-$(CONFIG_CPU_R5432)		+= pg-r5432.o c-r5432.o tlb-r4k.o tlbex-r4k.o
 obj-$(CONFIG_CPU_RM7000)	+= pg-rm7k.o c-rm7k.o tlb-r4k.o tlbex-r4k.o
 obj-$(CONFIG_CPU_R10000)	+= pg-andes.o c-andes.o tlb-r4k.o tlbex-r4k.o
-obj-$(CONFIG_CPU_MIPS32)	+= pg-mips32.o c-mips32.o tlb-r4k.o tlbex-r4k.o
+obj-$(CONFIG_CPU_MIPS32)	+= pg-mips32.o c-mips32.o tlb-r4k.o tlbex-mips32.o
 obj-$(CONFIG_CPU_MIPS64)	+= pg-mips32.o c-mips32.o tlb-r4k.o tlbex-r4k.o
 obj-$(CONFIG_CPU_SB1)		+= pg-sb1.o c-sb1.o tlb-sb1.o tlbex-r4k.o
 
diff -Naur --exclude=CVS linux-2.4-orig/arch/mips/mm/ioremap.c linux-2.4/arch/mips/mm/ioremap.c
--- linux-2.4-orig/arch/mips/mm/ioremap.c	Wed Nov 13 15:04:50 2002
+++ linux-2.4/arch/mips/mm/ioremap.c	Wed Dec 11 22:55:45 2002
@@ -94,6 +94,17 @@
 }
 
 /*
+ * Allow physical addresses to be fixed up to help 36 bit 
+ * peripherals.
+ */
+static phys_t def_fixup_bigphys_addr(phys_t phys_addr, phys_t size)
+{
+	return phys_addr;
+}
+
+phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size) = def_fixup_bigphys_addr;
+
+/*
  * Generic mapping function (not visible outside):
  */
 
@@ -107,7 +118,7 @@
  * caller shouldn't need to know that small detail.
  */
 
-#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL))
+#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL)  && !((phys_t)addr & 0xFFFFFFFF00000000))
 
 void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags)
 {
@@ -116,6 +127,8 @@
 	phys_t last_addr;
 	void * addr;
 
+	phys_addr = fixup_bigphys_addr(phys_addr, size);
+
 	/* Don't allow wraparound or zero size */
 	last_addr = phys_addr + size - 1;
 	if (!size || last_addr < phys_addr)
diff -Naur --exclude=CVS linux-2.4-orig/arch/mips/mm/tlb-r4k.c linux-2.4/arch/mips/mm/tlb-r4k.c
--- linux-2.4-orig/arch/mips/mm/tlb-r4k.c	Thu Dec  5 16:50:28 2002
+++ linux-2.4/arch/mips/mm/tlb-r4k.c	Tue Dec 10 22:14:30 2002
@@ -210,8 +210,14 @@
 	idx = read_c0_index();
 	ptep = pte_offset(pmdp, address);
 	BARRIER;
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+	write_c0_entrylo0(ptep->pte_high);
+	ptep++;
+	write_c0_entrylo1(ptep->pte_high);
+#else
 	write_c0_entrylo0(pte_val(*ptep++) >> 6);
 	write_c0_entrylo1(pte_val(*ptep) >> 6);
+#endif
 	write_c0_entryhi(address | pid);
 	BARRIER;
 	if (idx < 0) {
diff -Naur --exclude=CVS linux-2.4-orig/arch/mips/mm/tlbex-mips32.S linux-2.4/arch/mips/mm/tlbex-mips32.S
--- linux-2.4-orig/arch/mips/mm/tlbex-mips32.S	Wed Dec 31 16:00:00 1969
+++ linux-2.4/arch/mips/mm/tlbex-mips32.S	Tue Dec 10 22:14:30 2002
@@ -0,0 +1,329 @@
+/*
+ * TLB exception handling code for MIPS32 CPUs.
+ *
+ * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse
+ *
+ * Multi-cpu abstraction and reworking:
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ *
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * Pete Popov, ppopov@pacbell.net
+ * Added 36 bit phys address support.
+ * Copyright (C) 2002 MontaVista Software, Inc.
+ */
+#include <linux/init.h>
+
+#include <asm/asm.h>
+#include <asm/current.h>
+#include <asm/offset.h>
+#include <asm/cachectl.h>
+#include <asm/fpregdef.h>
+#include <asm/mipsregs.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+#define TLB_OPTIMIZE /* If you are paranoid, disable this. */
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+
+/* We really only support 36 bit physical addresses on MIPS32 */
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        4 /* pte_high contains pre-shifted, ready to go entry */
+#define PTE_SIZE        8
+#define PTEP_INDX_MSK	0xff0
+#define PTE_INDX_MSK	0xff8
+#define PTE_INDX_SHIFT 9
+#define CONVERT_PTE(pte)
+#define PTE_MAKEWRITE_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, (_PAGE_VALID | _PAGE_DIRTY)>>6; \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#define PTE_MAKEVALID_HIGH(pte, ptr) \
+	lw	pte, 4(ptr); \
+	ori	pte, pte, _PAGE_VALID>>6; \
+	sw	pte, 4(ptr); \
+	lw	pte, 0(ptr);
+
+#else
+
+#define PTE_L		lw
+#define PTE_S		sw
+#define PTE_SRL		srl
+#define P_MTC0		mtc0
+#define PTE_HALF        0
+#define PTE_SIZE	4
+#define PTEP_INDX_MSK	0xff8
+#define PTE_INDX_MSK	0xffc
+#define PTE_INDX_SHIFT	10
+#define CONVERT_PTE(pte) srl pte, pte, 6
+#define PTE_MAKEWRITE_HIGH(pte, ptr)
+#define PTE_MAKEVALID_HIGH(pte, ptr)
+
+#endif  /* CONFIG_64BIT_PHYS_ADDR */
+
+	__INIT
+
+#ifdef CONFIG_64BIT_PHYS_ADDR
+#define GET_PTE_OFF(reg)
+#else
+#define GET_PTE_OFF(reg)	srl	reg, reg, 1
+#endif
+
+/*	
+ * These handlers much be written in a relocatable manner
+ * because based upon the cpu type an arbitrary one of the
+ * following pieces of code will be copied to the KSEG0
+ * vector location.
+ */
+	/* TLB refill, EXL == 0, MIPS32 version */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4000)
+	.set	mips3
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_CONTEXT
+	la	k0, pgd_current
+	srl	k1, 23
+	sll	k1, 2				# log2(sizeof(pgd_t)
+	addu	k1, k0, k1
+	lw	k1, (k1)
+#else 
+	lw	k1, pgd_current			# get pgd pointer
+#endif	
+	nop
+	mfc0	k0, CP0_BADVADDR		# Get faulting address
+	srl	k0, k0, PGDIR_SHIFT		# get pgd only bits
+
+	sll	k0, k0, 2
+	addu	k1, k1, k0			# add in pgd offset
+	mfc0	k0, CP0_CONTEXT			# get context reg
+	lw	k1, (k1)
+	GET_PTE_OFF(k0)				# get pte offset
+	and	k0, k0, PTEP_INDX_MSK
+	addu	k1, k1, k0			# add in offset
+
+	PTE_L	k0, PTE_HALF(k1)		# get even pte
+	CONVERT_PTE(k0)
+	P_MTC0	k0, CP0_ENTRYLO0		# load it
+	PTE_L	k1, (PTE_HALF+PTE_SIZE)(k1)	# get odd pte
+	CONVERT_PTE(k1)
+	P_MTC0	k1, CP0_ENTRYLO1		# load it
+	b	1f
+	tlbwr					# write random tlb entry
+1:
+	nop
+	eret					# return from trap
+	END(except_vec0_r4000)
+
+/*
+ * These are here to avoid putting ifdefs in tlb-r4k.c
+ */
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_nevada)
+	.set	mips3
+	PANIC("Nevada Exception Vec 0 called")
+	END(except_vec0_nevada)
+
+	.set	noreorder
+	.set	noat
+	LEAF(except_vec0_r4600)
+	.set	mips3
+	PANIC("R4600 Exception Vec 0 called")
+	END(except_vec0_r4600)
+
+	__FINIT
+
+/*
+ * ABUSE of CPP macros 101.
+ *
+ * After this macro runs, the pte faulted on is
+ * in register PTE, a ptr into the table in which
+ * the pte belongs is in PTR.
+ */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, pgd_current;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);          
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, pgd_current;
+#endif
+
+#define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
+	mfc0	pte, CP0_BADVADDR; \
+	srl	pte, pte, PGDIR_SHIFT; \
+	sll	pte, pte, 2; \
+	addu	ptr, ptr, pte; \
+	mfc0	pte, CP0_BADVADDR; \
+	lw	ptr, (ptr); \
+	srl	pte, pte, PTE_INDX_SHIFT; \
+	and	pte, pte, PTE_INDX_MSK; \
+	addu	ptr, ptr, pte; \
+	PTE_L	pte, (ptr);
+
+	/* This places the even/odd pte pair in the page
+	 * table at PTR into ENTRYLO0 and ENTRYLO1 using
+	 * TMP as a scratch register.
+	 */
+#define PTE_RELOAD(ptr, tmp) \
+	ori	ptr, ptr, PTE_SIZE; \
+	xori	ptr, ptr, PTE_SIZE; \
+	PTE_L	tmp, (PTE_HALF+PTE_SIZE)(ptr); \
+	CONVERT_PTE(tmp); \
+	P_MTC0	tmp, CP0_ENTRYLO1; \
+	PTE_L	ptr, PTE_HALF(ptr); \
+	CONVERT_PTE(ptr); \
+	P_MTC0	ptr, CP0_ENTRYLO0;
+
+#define DO_FAULT(write) \
+	.set	noat; \
+	SAVE_ALL; \
+	mfc0	a2, CP0_BADVADDR; \
+	STI; \
+	.set	at; \
+	move	a0, sp; \
+	jal	do_page_fault; \
+	 li	a1, write; \
+	j	ret_from_exception; \
+	 nop; \
+	.set	noat;
+
+	/* Check is PTE is present, if not then jump to LABEL.
+	 * PTR points to the page table where this PTE is located,
+	 * when the macro is done executing PTE will be restored
+	 * with it's original value.
+	 */
+#define PTE_PRESENT(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_READ); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE valid, store result in PTR. */
+#define PTE_MAKEVALID(pte, ptr) \
+	ori	pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \
+	PTE_S	pte, (ptr);
+
+	/* Check if PTE can be written to, if not branch to LABEL.
+	 * Regardless restore PTE with value from PTR when done.
+	 */
+#define PTE_WRITABLE(pte, ptr, label) \
+	andi	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	xori	pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \
+	bnez	pte, label; \
+	PTE_L	pte, (ptr);
+
+	/* Make PTE writable, update software status bits as well,
+	 * then store at PTR.
+	 */
+#define PTE_MAKEWRITE(pte, ptr) \
+	ori	pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \
+			   _PAGE_VALID | _PAGE_DIRTY); \
+	PTE_S	pte, (ptr);
+
+	.set	noreorder
+
+#define R5K_HAZARD nop
+
+	.align	5
+	NESTED(handle_tlbl, PT_SIZE, sp)
+	.set	noat
+invalid_tlbl:
+#ifdef TLB_OPTIMIZE
+	/* Test present bit in entry. */
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp
+	PTE_PRESENT(k0, k1, nopage_tlbl)
+	PTE_MAKEVALID_HIGH(k0, k1)
+	PTE_MAKEVALID(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3	
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbl:
+	DO_FAULT(0)
+	END(handle_tlbl)
+
+	.align	5
+	NESTED(handle_tlbs, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+        li      k0,0
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp				# find faulting entry
+	PTE_WRITABLE(k0, k1, nopage_tlbs)
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nopage_tlbs:
+	DO_FAULT(1)
+	END(handle_tlbs)
+
+	.align	5
+	NESTED(handle_mod, PT_SIZE, sp)
+	.set	noat
+#ifdef TLB_OPTIMIZE
+	.set	mips3
+	LOAD_PTE(k0, k1)
+	R5K_HAZARD
+	tlbp					# find faulting entry
+	andi	k0, k0, _PAGE_WRITE
+	beqz	k0, nowrite_mod
+	PTE_L	k0, (k1)
+
+	/* Present and writable bits set, set accessed and dirty bits. */
+	PTE_MAKEWRITE(k0, k1)
+	PTE_MAKEWRITE_HIGH(k0, k1)
+	/* Now reload the entry into the tlb. */
+	PTE_RELOAD(k1, k0)
+	nop
+	b	1f
+	 tlbwi
+1:
+	nop
+	.set	mips3
+	eret
+	.set	mips0
+#endif
+
+nowrite_mod:
+	DO_FAULT(1)
+	END(handle_mod)
+
diff -Naur --exclude=CVS linux-2.4-orig/include/asm-mips/page.h linux-2.4/include/asm-mips/page.h
--- linux-2.4-orig/include/asm-mips/page.h	Sat Nov 16 21:39:31 2002
+++ linux-2.4/include/asm-mips/page.h	Fri Dec 13 20:19:10 2002
@@ -71,15 +71,22 @@
  * These are used to make use of C type-checking..
  */
 #ifdef CONFIG_64BIT_PHYS_ADDR
-typedef struct { unsigned long long pte; } pte_t;
+  #ifdef CONFIG_CPU_MIPS32
+    typedef struct { unsigned long pte_low, pte_high; } pte_t;
+    #define pte_val(x)    ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+  #else
+    typedef struct { unsigned long long pte_low; } pte_t;
+    #define pte_val(x)    ((x).pte_low)
+  #endif
 #else
-typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pte_low; } pte_t;
+#define pte_val(x)    ((x).pte_low)
 #endif
+
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
 
-#define pte_val(x)	((x).pte)
 #define pmd_val(x)	((x).pmd)
 #define pgd_val(x)	((x).pgd)
 #define pgprot_val(x)	((x).pgprot)
diff -Naur --exclude=CVS linux-2.4-orig/include/asm-mips/pgtable-2level.h linux-2.4/include/asm-mips/pgtable-2level.h
--- linux-2.4-orig/include/asm-mips/pgtable-2level.h	Wed Dec 31 16:00:00 1969
+++ linux-2.4/include/asm-mips/pgtable-2level.h	Fri Dec 13 20:19:10 2002
@@ -0,0 +1,62 @@
+#ifndef _MIPS_PGTABLE_2LEVEL_H
+#define _MIPS_PGTABLE_2LEVEL_H
+
+/*
+ * traditional mips two-level paging structure:
+ */
+
+#if defined(CONFIG_64BIT_PHYS_ADDR)
+#define PMD_SHIFT	21
+#define PTRS_PER_PTE	512
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PGD	2048
+#define PGD_ORDER	1
+#else
+#define PMD_SHIFT	22
+#define PTRS_PER_PTE	1024
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PGD	1024
+#define PGD_ORDER	0
+#endif
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
+#define pmd_ERROR(e) \
+	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+	printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
+
+static inline int pte_none(pte_t pte)    { return !(pte.pte_low); }
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+static inline void set_pte(pte_t *ptep, pte_t pteval)
+{
+	*ptep = pteval;
+#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX)
+	if (pte_val(pteval) & _PAGE_GLOBAL) {
+		pte_t *buddy = ptep_buddy(ptep);
+		/*
+		 * Make sure the buddy is global too (if it's !none,
+		 * it better already be global)
+		 */
+		if (pte_none(*buddy))
+			pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
+	}
+#endif
+}
+
+#ifdef CONFIG_CPU_VR41XX
+#define pte_page(x)  (mem_map+((unsigned long)(((x).pte_low >> (PAGE_SHIFT+2)))))
+#define __mk_pte(page_nr,pgprot) __pte(((page_nr) << (PAGE_SHIFT+2)) | pgprot_val(pgprot))
+#else
+#define pte_page(x)  (mem_map+((unsigned long)(((x).pte_low >> PAGE_SHIFT))))
+#define __mk_pte(page_nr,pgprot) __pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
+#endif
+
+#endif
+
+#endif /* _MIPS_PGTABLE_2LEVEL_H */
diff -Naur --exclude=CVS linux-2.4-orig/include/asm-mips/pgtable-3level.h linux-2.4/include/asm-mips/pgtable-3level.h
--- linux-2.4-orig/include/asm-mips/pgtable-3level.h	Wed Dec 31 16:00:00 1969
+++ linux-2.4/include/asm-mips/pgtable-3level.h	Tue Dec 10 22:14:30 2002
@@ -0,0 +1,63 @@
+#ifndef _MIPS_PGTABLE_3LEVEL_H
+#define _MIPS_PGTABLE_3LEVEL_H
+
+/*
+ * Not really a 3 level page table but we follow most of the x86 PAE code.
+ */
+
+#define PMD_SHIFT	21
+#define PTRS_PER_PTE	512
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PGD	2048
+#define PGD_ORDER	1
+
+#if !defined (_LANGUAGE_ASSEMBLY)
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
+#define pmd_ERROR(e) \
+	printk("%s:%d: bad pmd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
+#define pgd_ERROR(e) \
+	printk("%s:%d: bad pgd %p(%016Lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
+
+/*
+ * MIPS32 Note
+ * pte_low contains the 12 low bits only.  This includes the 6 lsb bits
+ * which contain software control bits, and the next 6 attribute bits 
+ * which are actually written in the entrylo[0,1] registers (G,V,D,Cache Mask).
+ * pte_high contains the 36 bit physical address and the 6 hardware 
+ * attribute bits (G,V,D, Cache Mask). The entry is already fully setup
+ * so in the tlb refill handler we do not need to shift right 6.
+ */
+
+/* Rules for using set_pte: the pte being assigned *must* be
+ * either not present or in a state where the hardware will
+ * not attempt to update the pte.  In places where this is
+ * not possible, use pte_get_and_clear to obtain the old pte
+ * value and then use set_pte to update it.  -ben
+ */
+static inline void set_pte(pte_t *ptep, pte_t pte)
+{
+	ptep->pte_high = (pte.pte_high & ~0x3f) | ((pte.pte_low>>6) & 0x3f);
+	ptep->pte_low = pte.pte_low;
+}
+
+static inline int pte_same(pte_t a, pte_t b)
+{
+	return a.pte_low == b.pte_low && a.pte_high == b.pte_high;
+}
+
+#define pte_page(x)    (mem_map+(((x).pte_high >> 6)))
+#define pte_none(x)    (!(x).pte_low && !(x).pte_high)
+
+static inline pte_t 
+__mk_pte(unsigned long page_nr, pgprot_t pgprot)
+{
+	pte_t pte;
+
+	pte.pte_high = (page_nr << 6) | (pgprot_val(pgprot) >> 6);
+	pte.pte_low = pgprot_val(pgprot);
+	return pte;
+}
+#endif
+
+#endif /* _MIPS_PGTABLE_3LEVEL_H */
diff -Naur --exclude=CVS linux-2.4-orig/include/asm-mips/pgtable.h linux-2.4/include/asm-mips/pgtable.h
--- linux-2.4-orig/include/asm-mips/pgtable.h	Sat Nov 16 21:39:31 2002
+++ linux-2.4/include/asm-mips/pgtable.h	Fri Dec 13 20:19:10 2002
@@ -13,6 +13,8 @@
 #include <asm/addrspace.h>
 #include <asm/page.h>
 
+#ifndef _LANGUAGE_ASSEMBLY
+
 #include <linux/linkage.h>
 #include <asm/cachectl.h>
 #include <asm/fixmap.h>
@@ -89,11 +91,8 @@
  */
 
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
-#ifdef CONFIG_64BIT_PHYS_ADDR
-#define PMD_SHIFT	21
-#else
-#define PMD_SHIFT	22
-#endif
+#endif /* !defined (_LANGUAGE_ASSEMBLY) */
+
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 
@@ -102,22 +101,6 @@
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 
-/*
- * Entries per page directory level: we use two-level, so
- * we don't really have any PMD directory physically.
- */
-#ifdef CONFIG_64BIT_PHYS_ADDR
-#define PTRS_PER_PTE	512
-#define PTRS_PER_PMD	1
-#define PTRS_PER_PGD	2048
-#define PGD_ORDER	1
-#else
-#define PTRS_PER_PTE	1024
-#define PTRS_PER_PMD	1
-#define PTRS_PER_PGD	1024
-#define PGD_ORDER	0
-#endif
-
 #define USER_PTRS_PER_PGD	(0x80000000UL/PGDIR_SIZE)
 #define FIRST_USER_PGD_NR	0
 
@@ -169,17 +152,13 @@
 #define __S110	PAGE_SHARED
 #define __S111	PAGE_SHARED
 
-#ifdef CONFIG_64BIT_PHYS_ADDR
-#define pte_ERROR(e) \
-	printk("%s:%d: bad pte %016Lx.\n", __FILE__, __LINE__, pte_val(e))
+#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_CPU_MIPS32)
+#include <asm/pgtable-3level.h>
 #else
-#define pte_ERROR(e) \
-	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#include <asm/pgtable-2level.h>
 #endif
-#define pmd_ERROR(e) \
-	printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
-#define pgd_ERROR(e) \
-	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+#if !defined (_LANGUAGE_ASSEMBLY)
 
 extern unsigned long empty_zero_page;
 extern unsigned long zero_page_mask;
@@ -205,40 +184,6 @@
 	pmd_val(*pmdp) = (((unsigned long) ptep) & PAGE_MASK);
 }
 
-static inline int pte_none(pte_t pte)    { return !(pte_val(pte) & ~_PAGE_GLOBAL); }
-static inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-static inline void set_pte(pte_t *ptep, pte_t pteval)
-{
-	*ptep = pteval;
-#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX)
-	if (pte_val(pteval) & _PAGE_GLOBAL) {
-		pte_t *buddy = ptep_buddy(ptep);
-		/*
-		 * Make sure the buddy is global too (if it's !none,
-		 * it better already be global)
-		 */
-		if (pte_none(*buddy))
-			pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
-	}
-#endif
-}
-
-static inline void pte_clear(pte_t *ptep)
-{
-#if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX)
-	/* Preserve global status for the pair */
-	if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
-		set_pte(ptep, __pte(_PAGE_GLOBAL));
-	else
-#endif
-		set_pte(ptep, __pte(0));
-}
-
 /*
  * (pmds are folded into pgds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
@@ -281,69 +226,70 @@
 static inline void pgd_clear(pgd_t *pgdp)	{ }
 
 /*
- * Permanent address of a page.  Obviously must never be called on a highmem
- * page.
- */
-#ifdef CONFIG_CPU_VR41XX
-#define pte_page(x)             (mem_map+(unsigned long)((pte_val(x) >> (PAGE_SHIFT + 2))))
-#else
-#define pte_page(x)		(mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
-#endif
-
-/*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-static inline int pte_read(pte_t pte)	{ return pte_val(pte) & _PAGE_READ; }
-static inline int pte_write(pte_t pte)	{ return pte_val(pte) & _PAGE_WRITE; }
-static inline int pte_dirty(pte_t pte)	{ return pte_val(pte) & _PAGE_MODIFIED; }
-static inline int pte_young(pte_t pte)	{ return pte_val(pte) & _PAGE_ACCESSED; }
+
+static inline int pte_present(pte_t pte) { return (pte.pte_low) & _PAGE_PRESENT; }
+
+static inline int pte_read(pte_t pte)	{ return (pte).pte_low & _PAGE_READ; }
+static inline int pte_write(pte_t pte)	{ return (pte).pte_low & _PAGE_WRITE; }
+static inline int pte_dirty(pte_t pte)	{ return (pte).pte_low & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte)	{ return (pte).pte_low & _PAGE_ACCESSED; }
+
+static inline void pte_clear(pte_t *ptep)
+{
+	set_pte(ptep, __pte(0));
+}
 
 static inline pte_t pte_wrprotect(pte_t pte)
 {
-	pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+	(pte).pte_low &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
 	return pte;
 }
 
 static inline pte_t pte_rdprotect(pte_t pte)
 {
-	pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	(pte).pte_low &= ~(_PAGE_READ | _PAGE_SILENT_READ);
 	return pte;
 }
 
 static inline pte_t pte_mkclean(pte_t pte)
 {
-	pte_val(pte) &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
+	(pte).pte_low &= ~(_PAGE_MODIFIED|_PAGE_SILENT_WRITE);
 	return pte;
 }
 
 static inline pte_t pte_mkold(pte_t pte)
 {
-	pte_val(pte) &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
+	(pte).pte_low &= ~(_PAGE_ACCESSED|_PAGE_SILENT_READ);
 	return pte;
 }
 
 static inline pte_t pte_mkwrite(pte_t pte)
 {
-	pte_val(pte) |= _PAGE_WRITE;
-	if (pte_val(pte) & _PAGE_MODIFIED)
-		pte_val(pte) |= _PAGE_SILENT_WRITE;
+	(pte).pte_low |= _PAGE_WRITE;
+	if ((pte).pte_low & _PAGE_MODIFIED) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+	}
 	return pte;
 }
 
 static inline pte_t pte_mkread(pte_t pte)
 {
-	pte_val(pte) |= _PAGE_READ;
-	if (pte_val(pte) & _PAGE_ACCESSED)
-		pte_val(pte) |= _PAGE_SILENT_READ;
+	(pte).pte_low |= _PAGE_READ;
+	if ((pte).pte_low & _PAGE_ACCESSED) {
+		(pte).pte_low |= _PAGE_SILENT_READ;
+	}
 	return pte;
 }
 
 static inline pte_t pte_mkdirty(pte_t pte)
 {
-	pte_val(pte) |= _PAGE_MODIFIED;
-	if (pte_val(pte) & _PAGE_WRITE)
-		pte_val(pte) |= _PAGE_SILENT_WRITE;
+	(pte).pte_low |= _PAGE_MODIFIED;
+	if ((pte).pte_low & _PAGE_WRITE) {
+		(pte).pte_low |= _PAGE_SILENT_WRITE;
+	}
 	return pte;
 }
 
@@ -366,9 +312,9 @@
 
 static inline pte_t pte_mkyoung(pte_t pte)
 {
-	pte_val(pte) |= _PAGE_ACCESSED;
-	if (pte_val(pte) & _PAGE_READ)
-		pte_val(pte) |= _PAGE_SILENT_READ;
+	(pte).pte_low |= _PAGE_ACCESSED;
+	if ((pte).pte_low & _PAGE_READ)
+		(pte).pte_low |= _PAGE_SILENT_READ;
 	return pte;
 }
 
@@ -376,43 +322,24 @@
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-
-#ifdef CONFIG_CPU_VR41XX
-#define mk_pte(page, pgprot)                                            \
-({                                                                      \
-        pte_t   __pte;                                                  \
-                                                                        \
-        pte_val(__pte) = ((phys_t)(page - mem_map) << (PAGE_SHIFT + 2)) | \
-                         pgprot_val(pgprot);                            \
-                                                                        \
-        __pte;                                                          \
-})
-#else
-#define mk_pte(page, pgprot)						\
-({									\
-	pte_t   __pte;							\
-									\
-	pte_val(__pte) = ((phys_t)(page - mem_map) << PAGE_SHIFT) | \
-	                 pgprot_val(pgprot);				\
-									\
-	__pte;								\
-})
-#endif
-
-static inline pte_t mk_pte_phys(phys_t physpage, pgprot_t pgprot)
-{
-#ifdef CONFIG_CPU_VR41XX
-        return __pte((physpage << 2) | pgprot_val(pgprot));
-#else
-	return __pte(physpage | pgprot_val(pgprot));
-#endif
-}
+#define mk_pte(page, pgprot) __mk_pte((page) - mem_map, (pgprot))
+#define mk_pte_phys(physpage, pgprot)	__mk_pte((physpage) >> PAGE_SHIFT, pgprot)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+	pte.pte_low &= _PAGE_CHG_MASK;
+	pte.pte_low |= pgprot_val(newprot);
+	return pte;
 }
 
+/*
+ * (pmds are folded into pgds so this doesnt get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
+
+
 #define page_pte(page) page_pte_prot(page, __pgprot(0))
 
 #define __pgd_offset(address)	pgd_index(address)
@@ -464,7 +391,7 @@
 #define SWP_ENTRY(type,offset)	((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
 #endif
 
-#define pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define pte_to_swp_entry(pte)	((swp_entry_t) { (pte).pte_low })
 #define swp_entry_to_pte(x)	((pte_t) { (x).val })
 

@@ -474,6 +401,8 @@
 
 #include <asm-generic/pgtable.h>
 
+#endif /* !defined (_LANGUAGE_ASSEMBLY) */
+
 /*
  * We provide our own get_unmapped area to cope with the virtual aliasing
  * constraints placed on us by the cache architecture.
diff -Naur --exclude=CVS linux-2.4-orig/include/linux/mm.h linux-2.4/include/linux/mm.h
--- linux-2.4-orig/include/linux/mm.h	Sat Nov 16 21:39:31 2002
+++ linux-2.4/include/linux/mm.h	Fri Dec 13 20:19:10 2002
@@ -473,7 +473,7 @@
 
 extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size);
 extern int copy_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma);
-extern int remap_page_range(unsigned long from, unsigned long to, unsigned long size, pgprot_t prot);
+extern int remap_page_range(unsigned long from, phys_t to, unsigned long size, pgprot_t prot);
 extern int zeromap_page_range(unsigned long from, unsigned long size, pgprot_t prot);
 
 extern int vmtruncate(struct inode * inode, loff_t offset);
diff -Naur --exclude=CVS linux-2.4-orig/mm/memory.c linux-2.4/mm/memory.c
--- linux-2.4-orig/mm/memory.c	Wed Nov 13 15:08:45 2002
+++ linux-2.4/mm/memory.c	Fri Dec 13 20:15:39 2002
@@ -824,7 +824,7 @@
  * in null mappings (currently treated as "copy-on-access")
  */
 static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
-	unsigned long phys_addr, pgprot_t prot)
+	phys_t phys_addr, pgprot_t prot)
 {
 	unsigned long end;
 
@@ -848,7 +848,7 @@
 }
 
 static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-	unsigned long phys_addr, pgprot_t prot)
+	phys_t phys_addr, pgprot_t prot)
 {
 	unsigned long end;
 
@@ -868,8 +868,9 @@
 	return 0;
 }
 
+extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size);
 /*  Note: this is only safe if the mm semaphore is held when called. */
-int remap_page_range(unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot)
+int remap_page_range(unsigned long from, phys_t phys_addr, unsigned long size, pgprot_t prot)
 {
 	int error = 0;
 	pgd_t * dir;
@@ -877,6 +878,7 @@
 	unsigned long end = from + size;
 	struct mm_struct *mm = current->mm;
 
+	phys_addr = fixup_bigphys_addr(phys_addr, size);
 	phys_addr -= from;
 	dir = pgd_offset(mm, from);
 	flush_cache_range(mm, beg, end);

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-11-18 23:20 ` patch Rik van Riel
@ 2002-11-19  7:33   ` Duncan Sands
  0 siblings, 0 replies; 80+ messages in thread
From: Duncan Sands @ 2002-11-19  7:33 UTC (permalink / raw)
  To: Rik van Riel, deepak; +Cc: linux-kernel

On Tuesday 19 November 2002 00:20, Rik van Riel wrote:
> On Mon, 18 Nov 2002, deepak wrote:
> > how do i uninstall a patch
>
> $ man patch
> ...
>        -R  or  --reverse
>           Assume that this patch was created with the old and new
>           files swapped.  (Yes, I'm afraid that does happen occa­
>           sionally,  human  nature  being  what  it  is.)   patch
>           attempts  to  swap each hunk around before applying it.
>           Rejects come out in the swapped format.  The -R  option
> 	  ...
>
> Next time you should read the man page yourself ;)

Come on, be fair.  This text is pretty obscure.  If you didn't know so
already, would you understand from it that -R undoes a patch?

Duncan.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-11-18 23:07 patch deepak
@ 2002-11-18 23:20 ` Rik van Riel
  2002-11-19  7:33   ` patch Duncan Sands
  0 siblings, 1 reply; 80+ messages in thread
From: Rik van Riel @ 2002-11-18 23:20 UTC (permalink / raw)
  To: deepak; +Cc: linux-kernel

On Mon, 18 Nov 2002, deepak wrote:

> how do i uninstall a patch

$ man patch
...
       -R  or  --reverse
          Assume that this patch was created with the old and new
          files swapped.  (Yes, I'm afraid that does happen occa­
          sionally,  human  nature  being  what  it  is.)   patch
          attempts  to  swap each hunk around before applying it.
          Rejects come out in the swapped format.  The -R  option
	  ...

Next time you should read the man page yourself ;)

Rik
-- 
Bravely reimplemented by the knights who say "NIH".
http://www.surriel.com/		http://guru.conectiva.com/
Current spamtrap:  <a href=mailto:"october@surriel.com">october@surriel.com</a>


^ permalink raw reply	[flat|nested] 80+ messages in thread

* patch
@ 2002-11-18 23:07 deepak
  2002-11-18 23:20 ` patch Rik van Riel
  0 siblings, 1 reply; 80+ messages in thread
From: deepak @ 2002-11-18 23:07 UTC (permalink / raw)
  To: linux-kernel

how do i uninstall a patch


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-08-26  0:35 patch Russell Coker
  2002-08-26 17:15 ` patch Stephen Smalley
@ 2002-08-26 17:37 ` Stephen Smalley
  1 sibling, 0 replies; 80+ messages in thread
From: Stephen Smalley @ 2002-08-26 17:37 UTC (permalink / raw)
  To: Russell Coker; +Cc: SE Linux


On Mon, 26 Aug 2002, Russell Coker wrote:

> This patch adds some new attributes and appropriate use of them.  Also it
> corrects some errors in attribute usage.

Two other changes to this patch:
1) The patch omitted the necessary corresponding change to can_create_pty.
2) The patch left some redundant ssh-related rules later in user_macros.te
after adding duplicates to an earlier ssh-related section.

These should now be fixed in CVS.

--
Stephen D. Smalley, NAI Labs
ssmalley@nai.com





--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-08-26  0:35 patch Russell Coker
@ 2002-08-26 17:15 ` Stephen Smalley
  2002-08-26 17:37 ` patch Stephen Smalley
  1 sibling, 0 replies; 80+ messages in thread
From: Stephen Smalley @ 2002-08-26 17:15 UTC (permalink / raw)
  To: Russell Coker; +Cc: SE Linux


On Mon, 26 Aug 2002, Russell Coker wrote:

> This patch adds some new attributes and appropriate use of them.  Also it
> corrects some errors in attribute usage.
>
> I hope you'll accept these patches (or equivalent policy) into your tree and
> that we can come to a decision on what to do with devfs_t (whether to keep it
> or remove it) shortly.  Then it will be a lot easier to sort out the rest of
> the diffs.

Thanks, merged and available in the sourceforge CVS, without the
sysadm_devpts_t access.

--
Stephen D. Smalley, NAI Labs
ssmalley@nai.com





--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* patch
@ 2002-08-26  0:35 Russell Coker
  2002-08-26 17:15 ` patch Stephen Smalley
  2002-08-26 17:37 ` patch Stephen Smalley
  0 siblings, 2 replies; 80+ messages in thread
From: Russell Coker @ 2002-08-26  0:35 UTC (permalink / raw)
  To: SE Linux

[-- Attachment #1: Type: text/plain, Size: 868 bytes --]

This patch adds some new attributes and appropriate use of them.  Also it 
corrects some errors in attribute usage.

Steve, this and the other three patch files comprise about a quarted of the 
difference between your policy and my current tree.  The devfs_t is another 
quarter of the difference.

Of the remaining 1000 lines of patch about half is related to the 
sysadm_devpts_t issue for daemon startup.

I hope you'll accept these patches (or equivalent policy) into your tree and 
that we can come to a decision on what to do with devfs_t (whether to keep it 
or remove it) shortly.  Then it will be a lot easier to sort out the rest of 
the diffs.

-- 
I do not get viruses because I do not use MS software.
If you use Outlook then please do not put my email address in your
address-book so that WHEN you get a virus it won't use my address in the
>From field.

[-- Attachment #2: attrib.diff --]
[-- Type: text/x-diff, Size: 11398 bytes --]

diff -ruN /tmp/selinux/policy/attrib.te ./attrib.te
--- /tmp/selinux/policy/attrib.te	2002-08-21 20:22:42.000000000 +0200
+++ ./attrib.te	2002-08-25 18:08:35.000000000 +0200
@@ -119,6 +119,9 @@
 # to all user domains.
 attribute userdomain;
 
+# attribute for all non-administrative devpts types
+attribute userpty_type;
+
 # The user_crond_domain attribute identifies every user_crond domain, presently
 # user_crond_t and sysadm_crond_t.  It is used in TE rules that should be
 # applied to all user domains.
@@ -178,6 +181,13 @@
 # domains the ability to remove all such files (e.g. init, crond).
 attribute tmpfile;
 
+# The user_tmpfile attribute identifies all types associated with temporary
+# files for unpriv_userdomain domains.
+attribute user_tmpfile;
+
+# for the user_xserver_tmp_t etc
+attribute xserver_tmpfile;
+
 # The tmpfsfile attribute identifies all types defined for tmpfs 
 # type transitions. 
 # It is used in TE rules to grant certain domains the ability to
@@ -239,6 +249,10 @@
 # Identifier for log files or directories that only exist for log files.
 attribute logfile;
 
+# Identifier for lock files (/var/lock/*) or directories that only exist for
+# lock files.
+attribute lockfile;
+
 
 
 ##############################
diff -ruN /tmp/selinux/policy/domains/program/bootloader.te ./domains/program/bootloader.te
--- /tmp/selinux/policy/domains/program/bootloader.te	2002-08-21 20:22:43.000000000 +0200
+++ ./domains/program/bootloader.te	2002-08-25 00:49:03.000000000 +0200
@@ -76,6 +78,11 @@
 allow bootloader_t sysadm_tty_device_t:chr_file rw_file_perms;
 allow bootloader_t sysadm_devpts_t:chr_file rw_file_perms;
 
+ifdef(`dpkg.te', `
+# for making an initrd
+can_exec_read(bootloader_t, { mount_exec_t })
+')
+
 # for reading BIOS data
 allow bootloader_t memory_device_t:chr_file r_file_perms;
 
diff -ruN /tmp/selinux/policy/domains/program/checkpolicy.te ./domains/program/checkpolicy.te
--- /tmp/selinux/policy/domains/program/checkpolicy.te	2002-08-15 21:22:06.000000000 +0200
+++ ./domains/program/checkpolicy.te	2002-08-26 01:03:45.000000000 +0200
@@ -55,5 +55,5 @@
 # so it can be used without privilege to write real binary policy file
 can_exec(user_t, checkpolicy_exec_t)
 
-allow checkpolicy_t privrole:fd use;
+allow checkpolicy_t privfd:fd use;
 
diff -ruN /tmp/selinux/policy/domains/program/dpkg.te ./domains/program/dpkg.te
--- /tmp/selinux/policy/domains/program/dpkg.te	2002-08-21 20:22:44.000000000 +0200
+++ ./domains/program/dpkg.te	2002-08-26 01:04:04.000000000 +0200
@@ -101,7 +101,7 @@
 
 # allow user domains to execute dpkg
 allow userdomain dpkg_exec_t:dir r_dir_perms;
-can_exec(user_t, { dpkg_exec_t apt_exec_t })
+can_exec(userdomain, { dpkg_exec_t apt_exec_t })
 
 # allow everyone to read dpkg database
 r_dir_file({ apt_t userdomain }, { var_lib_dpkg_t var_lib_apt_t var_cache_apt_t })
diff -ruN /tmp/selinux/policy/domains/program/initrc.te ./domains/program/initrc.te
--- /tmp/selinux/policy/domains/program/initrc.te	2002-08-21 20:22:44.000000000 +0200
+++ ./domains/program/initrc.te	2002-08-25 18:09:09.000000000 +0200
@@ -9,7 +9,7 @@
 # initrc_t is the domain of the init rc scripts.
 # initrc_exec_t is the type of the init program.
 #
-type initrc_t, domain, privlog, privowner;
+type initrc_t, domain, privlog, privowner, privmail;
 role system_r types initrc_t;
 every_domain(initrc_t)
 type initrc_exec_t, file_type, sysadmfile, exec_type;
@@ -95,6 +95,10 @@
 allow initrc_t var_log_t:file { setattr rw_file_perms };
 allow initrc_t lastlog_t:file { setattr rw_file_perms };
 
+# remove old locks
+allow initrc_t lockfile:dir rw_dir_perms;
+allow initrc_t lockfile:file { getattr unlink };
+
 # Access /var/lib/random-seed.
 allow initrc_t var_lib_t:file rw_file_perms;
 allow initrc_t var_lib_t:file unlink;
@@ -140,9 +144,11 @@
 allow initrc_t ttyfile:chr_file relabelfrom;
 allow initrc_t tty_device_t:chr_file relabelto;
 
+ifdef(`rpm.te', `
 # Create and read /boot/kernel.h.
 allow initrc_t boot_t:lnk_file r_file_perms;
 file_type_auto_trans(initrc_t, boot_t, boot_runtime_t)
+')
 
 # Delete and re-create /boot/System.map.
 allow initrc_t boot_t:dir { read getattr write remove_name add_name };
diff -ruN /tmp/selinux/policy/domains/program/ipsec.te ./domains/program/ipsec.te
--- /tmp/selinux/policy/domains/program/ipsec.te	2002-08-21 20:22:44.000000000 +0200
+++ ./domains/program/ipsec.te	2002-08-25 19:51:54.000000000 +0200
@@ -25,7 +25,7 @@
 
 type ipsec_mgmt_t, domain, privlog, admin;
 type ipsec_mgmt_exec_t, file_type, sysadmfile, exec_type;
-type ipsec_mgmt_var_run_t, file_type, sysadmfile;
+type ipsec_mgmt_var_run_t, file_type, sysadmfile, pidfile;
 domain_auto_trans(ipsec_mgmt_t, ipsec_exec_t, ipsec_t)
 file_type_auto_trans(ipsec_mgmt_t, var_run_t, ipsec_mgmt_var_run_t)
 
@@ -214,6 +214,7 @@
 
 dontaudit ipsec_mgmt_t devpts_t:dir { getattr read };
 dontaudit ipsec_mgmt_t tty_device_t:chr_file getattr;
+dontaudit ipsec_mgmt_t device_t:dir { getattr read };
 
 allow ipsec_mgmt_t { sysadm_tty_device_t sysadm_devpts_t }:chr_file { read write ioctl };
 allow ipsec_t { sysadm_tty_device_t sysadm_devpts_t }:chr_file { read write };
diff -ruN /tmp/selinux/policy/domains/program/kcheckpass.te ./domains/program/kcheckpass.te
--- /tmp/selinux/policy/domains/program/kcheckpass.te	2002-08-22 16:21:26.000000000 +0200
+++ ./domains/program/kcheckpass.te	2002-08-25 18:27:42.000000000 +0200
@@ -19,7 +19,7 @@
 allow kcheckpass_t sbin_t:dir search;
 allow kcheckpass_t self:fifo_file { read write ioctl };
 allow kcheckpass_t self:unix_stream_socket create_stream_socket_perms;
-allow kcheckpass_t { user_t sysadm_t }:unix_stream_socket { read write ioctl };
+allow kcheckpass_t userdomain:unix_stream_socket { read write ioctl };
 allow kcheckpass_t self:unix_dgram_socket create_socket_perms;
 
 allow kcheckpass_t self:process { fork sigchld };
@@ -32,4 +32,5 @@
 
 dontaudit kcheckpass_t user_home_dir_type:dir search;
 dontaudit kcheckpass_t xdm_t:fd use;
-dontaudit kcheckpass_t user_tmp_t:file read;
+dontaudit kcheckpass_t user_tmpfile:file read;
+dontaudit kcheckpass_t device_t:dir search;
diff -ruN /tmp/selinux/policy/domains/program/ssh.te ./domains/program/ssh.te
--- /tmp/selinux/policy/domains/program/ssh.te	2002-08-21 20:22:46.000000000 +0200
+++ ./domains/program/ssh.te	2002-08-25 18:13:50.000000000 +0200
@@ -83,7 +90,7 @@
 
 # Relabel and access ptys created by sshd
 allow sshd_t sshd_devpts_t:chr_file { setattr getattr relabelfrom relabelto };
-allow sshd_t user_devpts_t:chr_file { setattr relabelto rw_file_perms };
+allow sshd_t { sysadm_devpts_t userpty_type }:chr_file { setattr relabelto rw_file_perms };
 
 #################################
 #
@@ -101,7 +108,7 @@
 
 # Relabel ptys created by sshd
 allow sshd_login_t sshd_devpts_t:chr_file { relabelfrom relabelto };
-allow sshd_login_t user_devpts_t:chr_file { getattr relabelfrom relabelto };
+allow sshd_login_t { sysadm_devpts_t userpty_type }:chr_file { getattr relabelfrom relabelto };
 
 # Obtain the SID for the user
 allow sshd_t security_t:security get_user_sids;
diff -ruN /tmp/selinux/policy/macros/admin_macros.te ./macros/admin_macros.te
--- /tmp/selinux/policy/macros/admin_macros.te	2002-08-21 20:22:47.000000000 +0200
+++ ./macros/admin_macros.te	2002-08-25 18:55:18.000000000 +0200
@@ -82,12 +84,12 @@
 
 # Create files in /tmp/orbit-* and /tmp/.ICE-unix
 # with our derived tmp type rather than user_tmp_t.
-file_type_auto_trans($1_t, user_tmp_t, $1_tmp_t)
+file_type_auto_trans($1_t, user_tmpfile, $1_tmp_t)
 
 ifdef(`xserver.te',
 `# Create files in /tmp/.X11-unix with our X servers derived
 # tmp type rather than user_xserver_tmp_t.
-file_type_auto_trans($1_xserver_t, user_xserver_tmp_t, $1_xserver_tmp_t)')
+file_type_auto_trans($1_xserver_t, xserver_tmpfile, $1_xserver_tmp_t)')
 
 #
 # A user who is authorized for sysadm_t may nonetheless have
diff -ruN /tmp/selinux/policy/macros/user_macros.te ./macros/user_macros.te
--- /tmp/selinux/policy/macros/user_macros.te	2002-08-22 17:15:07.000000000 +0200
+++ ./macros/user_macros.te	2002-08-25 00:31:53.000000000 +0200
@@ -16,23 +16,24 @@
 define(`user_domain',`
 # Use capabilities
 allow $1_t self:capability { net_bind_service dac_override setuid setgid chown sys_tty_config fowner };
+dontaudit $1_t self:capability { sys_nice fsetid };
 
 # Type for home directory.
 ifelse($1, sysadm, `
 type $1_home_dir_t, file_type, sysadmfile, home_dir_type, home_type;
 type $1_home_t, file_type, sysadmfile, home_type;
+type $1_tmp_t, file_type, sysadmfile, tmpfile;
 ', `
 type $1_home_dir_t, file_type, sysadmfile, home_dir_type, user_home_dir_type, home_type, user_home_type;
 type $1_home_t, file_type, sysadmfile, home_type, user_home_type;
 # do not allow privhome access to sysadm_home_dir_t
 file_type_auto_trans(privhome, $1_home_dir_t, $1_home_t)
+type $1_tmp_t, file_type, sysadmfile, tmpfile, user_tmpfile;
 ')
 
 # Create, access, and remove files in home directory.
 file_type_auto_trans($1_t, $1_home_dir_t, $1_home_t)
 
-# Type for temporary files.
-type $1_tmp_t, file_type, sysadmfile, tmpfile;
 # Use the type when creating files in /tmp.
 file_type_auto_trans($1_t, tmp_t, $1_tmp_t)
 # Bind to a Unix domain socket in /tmp.
@@ -44,15 +45,40 @@
 allow $1_t $1_tty_device_t:chr_file { setattr rw_file_perms };
 # Use the type when relabeling terminal devices.
 type_change $1_t tty_device_t:chr_file $1_tty_device_t;
+ifdef(`dpkg.te', `
+# Debian login is from shadow utils and does not allow resetting the perms.
+# have to fix this!
+type_change $1_t ttyfile:chr_file $1_tty_device_t;
+')
 
 # Type and access for pty devices.
+ifelse(`$1', `sysadm', `
 can_create_pty($1)
+', `
+can_create_pty($1, `, userpty_type')
+')
+
 # Use the type when relabeling pty devices.
 ifdef(`rlogind.te',
 `type_change $1_t rlogind_devpts_t:chr_file $1_devpts_t;')
 ifdef(`ssh.te', `
 type_change $1_t sshd_devpts_t:chr_file $1_devpts_t;
-')
+
+# Access /tmp/ssh files.
+allow $1_t sshd_tmp_t:dir rw_dir_perms;
+allow $1_t sshd_tmp_t:file create_file_perms;
+
+# Connect to sshd.
+can_tcp_connect($1_t, sshd_t)
+
+# Connect to ssh proxy.
+can_tcp_connect($1_t, $1_ssh_t)
+
+allow $1_t sshd_t:fd use;
+allow $1_t sshd_t:tcp_socket rw_stream_socket_perms;
+# Use a Unix stream socket inherited from sshd.
+allow $1_t sshd_t:unix_stream_socket rw_stream_socket_perms;
+')dnl end of ssh section
 
 # Type for tmpfs/shm files.
 type $1_tmpfs_t, file_type, sysadmfile, tmpfsfile;
@@ -60,12 +86,6 @@
 file_type_auto_trans($1_t, tmpfs_t, $1_tmpfs_t)
 allow $1_tmpfs_t tmpfs_t:filesystem associate;
 
-# Access /tmp/ssh files.
-ifdef(`ssh.te', `
-allow $1_t sshd_tmp_t:dir rw_dir_perms;
-allow $1_t sshd_tmp_t:file create_file_perms;
-')
-
 # Read and write /var/catman.
 allow $1_t catman_t:dir rw_dir_perms;
 allow $1_t catman_t:notdevfile_class_set create_file_perms;
diff -ruN /tmp/selinux/policy/types/file.te ./types/file.te
--- /tmp/selinux/policy/types/file.te	2002-08-21 20:22:48.000000000 +0200
+++ ./types/file.te	2002-08-25 18:15:48.000000000 +0200
@@ -159,7 +155,7 @@
 type var_run_t, file_type, sysadmfile;
 type var_log_t, file_type, sysadmfile, logfile;
 type faillog_t, file_type, sysadmfile, logfile;
-type var_lock_t, file_type, sysadmfile;
+type var_lock_t, file_type, sysadmfile, lockfile;
 type var_lib_t, file_type, sysadmfile;
 # for /var/{spool,lib}/texmf index files
 type tetex_data_t, file_type, sysadmfile, tmpfile;

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-07-16 18:00       ` PATCH Pete Popov
@ 2002-07-17  0:29         ` Vivien Chappelier
  0 siblings, 0 replies; 80+ messages in thread
From: Vivien Chappelier @ 2002-07-17  0:29 UTC (permalink / raw)
  To: Pete Popov; +Cc: linux-mips

On 16 Jul 2002, Pete Popov wrote:

> > But Vivien Chappelier said it fixed his X server problem in mips64.
> I think the upper 32 bits get zeroed out.  The fact that it fixed Vivien's
> problem confirms this (he was running oss, right?)

Well.. sorry guys, it seems it works with the old version as well
now.. don't know what I messed up..
Anyway, on mips64, pte_t is an unsigned long, which is 64 bit, but
PAGE_MASK in PAGE_CHG_MASK is 1UL << something, so it's 64 bit as
well. Thus I guess there no problem with the old implementation in
fact. (the problem was with me..)

Sorry,
Vivien Chappelier.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-07-16 17:43     ` PATCH Joe George
@ 2002-07-16 18:00       ` Pete Popov
  2002-07-17  0:29         ` PATCH Vivien Chappelier
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2002-07-16 18:00 UTC (permalink / raw)
  To: Joe George; +Cc: Ralf Baechle, linux-mips

On Tue, 2002-07-16 at 10:43, Joe George wrote:
> I'll disagree with both of you so I may learn from the flames. :-)
 
> First it's true the patch wasn't formatted for oss and should have
> been rejected on that basis.  At least my patches would be. :)

Well, my agreement with Ralf was that the patch wasn't formatted for the
oss tree, not that it's not applicable.
 
> But Vivien Chappelier said it fixed his X server problem in mips64.
> CONFIG_64BIT_PHYS_ADDR is applicable to both 36 and 64
> bit code, I think.
> 
> So the crux of my question is, if an unsigned long long pte is
> and'ed with an unsigned long PAGE_CHG_MASK what happens
> to the upper 32 bits of pte.  On a 64 bit processor is PAGE_CHG_MASK
> sign extended so everything is fine, or does it zero the upper
> 32 bits?

I think the upper 32 bits get zeroed out.  The fact that it fixed Vivien's
problem confirms this (he was running oss, right?)

Pete

 
> Joe
> 
> 
> Pete Popov wrote:
> > On Tue, 2002-07-16 at 08:07, Ralf Baechle wrote:
> > 
> >>On Mon, Jul 15, 2002 at 03:29:10PM -0700, Pete Popov wrote:
> >>
> >>
> >>>--- include/asm-mips/pgtable.h.old	Fri Jul 12 17:25:19 2002
> >>>+++ include/asm-mips/pgtable.h	Fri Jul 12 17:25:36 2002
> >>>@@ -332,7 +332,9 @@
> >>> 
> >>> static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> >>> {
> >>>-	return __pte(((pte).pte_low & _PAGE_CHG_MASK) | pgprot_val(newprot));
> >>>+	pte.pte_low &= _PAGE_CHG_MASK;
> >>>+	pte.pte_low |= pgprot_val(newprot);
> >>>+	return pte;
> >>> }
> >>>
> >>This patch certainly doesn't apply to oss.  Seems somebody did copy all
> >>the x86 pte_t and stuff into your tree without too much thinking ...
> >>
> > 
> > That's right, I forgot you don't have the 36 bit code that uses pte_low
> > and pte_high.  
> > 
> > Pete
> > 
> 
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-07-16 15:15   ` PATCH Pete Popov
@ 2002-07-16 17:43     ` Joe George
  2002-07-16 18:00       ` PATCH Pete Popov
  0 siblings, 1 reply; 80+ messages in thread
From: Joe George @ 2002-07-16 17:43 UTC (permalink / raw)
  To: Pete Popov; +Cc: Ralf Baechle, linux-mips

I'll disagree with both of you so I may learn from the flames. :-)

First it's true the patch wasn't formatted for oss and should have
been rejected on that basis.  At least my patches would be. :)

But Vivien Chappelier said it fixed his X server problem in mips64.
CONFIG_64BIT_PHYS_ADDR is applicable to both 36 and 64
bit code, I think.

So the crux of my question is, if an unsigned long long pte is
and'ed with an unsigned long PAGE_CHG_MASK what happens
to the upper 32 bits of pte.  On a 64 bit processor is PAGE_CHG_MASK
sign extended so everything is fine, or does it zero the upper
32 bits?

Joe


Pete Popov wrote:
> On Tue, 2002-07-16 at 08:07, Ralf Baechle wrote:
> 
>>On Mon, Jul 15, 2002 at 03:29:10PM -0700, Pete Popov wrote:
>>
>>
>>>--- include/asm-mips/pgtable.h.old	Fri Jul 12 17:25:19 2002
>>>+++ include/asm-mips/pgtable.h	Fri Jul 12 17:25:36 2002
>>>@@ -332,7 +332,9 @@
>>> 
>>> static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
>>> {
>>>-	return __pte(((pte).pte_low & _PAGE_CHG_MASK) | pgprot_val(newprot));
>>>+	pte.pte_low &= _PAGE_CHG_MASK;
>>>+	pte.pte_low |= pgprot_val(newprot);
>>>+	return pte;
>>> }
>>>
>>This patch certainly doesn't apply to oss.  Seems somebody did copy all
>>the x86 pte_t and stuff into your tree without too much thinking ...
>>
> 
> That's right, I forgot you don't have the 36 bit code that uses pte_low
> and pte_high.  
> 
> Pete
> 

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-07-16 15:07 ` PATCH Ralf Baechle
@ 2002-07-16 15:15   ` Pete Popov
  2002-07-16 17:43     ` PATCH Joe George
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2002-07-16 15:15 UTC (permalink / raw)
  To: Ralf Baechle; +Cc: linux-mips

On Tue, 2002-07-16 at 08:07, Ralf Baechle wrote:
> On Mon, Jul 15, 2002 at 03:29:10PM -0700, Pete Popov wrote:
> 
> > --- include/asm-mips/pgtable.h.old	Fri Jul 12 17:25:19 2002
> > +++ include/asm-mips/pgtable.h	Fri Jul 12 17:25:36 2002
> > @@ -332,7 +332,9 @@
> >  
> >  static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
> >  {
> > -	return __pte(((pte).pte_low & _PAGE_CHG_MASK) | pgprot_val(newprot));
> > +	pte.pte_low &= _PAGE_CHG_MASK;
> > +	pte.pte_low |= pgprot_val(newprot);
> > +	return pte;
> >  }
> 
> This patch certainly doesn't apply to oss.  Seems somebody did copy all
> the x86 pte_t and stuff into your tree without too much thinking ...

That's right, I forgot you don't have the 36 bit code that uses pte_low
and pte_high.  

Pete

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: PATCH
  2002-07-15 22:29 PATCH Pete Popov
@ 2002-07-16 15:07 ` Ralf Baechle
  2002-07-16 15:15   ` PATCH Pete Popov
  0 siblings, 1 reply; 80+ messages in thread
From: Ralf Baechle @ 2002-07-16 15:07 UTC (permalink / raw)
  To: Pete Popov; +Cc: linux-mips

On Mon, Jul 15, 2002 at 03:29:10PM -0700, Pete Popov wrote:

> --- include/asm-mips/pgtable.h.old	Fri Jul 12 17:25:19 2002
> +++ include/asm-mips/pgtable.h	Fri Jul 12 17:25:36 2002
> @@ -332,7 +332,9 @@
>  
>  static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
>  {
> -	return __pte(((pte).pte_low & _PAGE_CHG_MASK) | pgprot_val(newprot));
> +	pte.pte_low &= _PAGE_CHG_MASK;
> +	pte.pte_low |= pgprot_val(newprot);
> +	return pte;
>  }

This patch certainly doesn't apply to oss.  Seems somebody did copy all
the x86 pte_t and stuff into your tree without too much thinking ...

  Ralf

^ permalink raw reply	[flat|nested] 80+ messages in thread

* PATCH
@ 2002-07-15 22:29 Pete Popov
  2002-07-16 15:07 ` PATCH Ralf Baechle
  0 siblings, 1 reply; 80+ messages in thread
From: Pete Popov @ 2002-07-15 22:29 UTC (permalink / raw)
  To: linux-mips

Ralf,

__pte is broken when pte_t is a 64bit type.  I did this to fix the 36
bit IO support for the Alchemy boards, but it also affects the 64 bit
mips port.  Apparently it fixed a Xfree problem someone was having.

Pete

--- include/asm-mips/pgtable.h.old	Fri Jul 12 17:25:19 2002
+++ include/asm-mips/pgtable.h	Fri Jul 12 17:25:36 2002
@@ -332,7 +332,9 @@
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-	return __pte(((pte).pte_low & _PAGE_CHG_MASK) | pgprot_val(newprot));
+	pte.pte_low &= _PAGE_CHG_MASK;
+	pte.pte_low |= pgprot_val(newprot);
+	return pte;
 }
 
 /*

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-05-23 11:33 ` patch Wilbert Knol
  2002-05-23 16:01   ` patch Richard Adams
@ 2002-05-24 14:14   ` Tomi Manninen
  1 sibling, 0 replies; 80+ messages in thread
From: Tomi Manninen @ 2002-05-24 14:14 UTC (permalink / raw)
  To: linux-hams

On Thu, 23 May 2002, Wilbert Knol wrote:

> On a related note...I am not sure if this applies to the kernel sources 
> Red Hat distibutes...but I haven't had much luck applying official kernel 
> patches against 'distributed' kernel source trees.

I think distribution kernels tend to have quite a lot of patches already 
applied. For example the default kernel on RH7.2 has over 200 patches 
totalling about million lines... So you should expect problems with 
patches that are intended for official kernels.

By the way, I just installed RH7.3 to one box and it seems it has all the
recent AX.25 patches included. Also the default build has the ax25, netrom
and rose modules. Unfortunately they didn't include most of the ax25
device drivers like mkiss, scc, etc. Soundmodem is there so if one is
building a packet radio box and is going to use soundmodem, you don't
need to recompile the kernel.

Just in case somene is doing just that...

-- 
Tomi Manninen           Internet:  oh2bns@sral.fi
OH2BNS                  AX.25:     oh2bns@oh2rbi.fin.eu
KP20ME04                Amprnet:   oh2bns@oh2rbi.ampr.org


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-05-23 11:33 ` patch Wilbert Knol
@ 2002-05-23 16:01   ` Richard Adams
  2002-05-24 14:14   ` patch Tomi Manninen
  1 sibling, 0 replies; 80+ messages in thread
From: Richard Adams @ 2002-05-23 16:01 UTC (permalink / raw)
  To: Wilbert Knol, linux-hams

On Thursday 23 May 2002 11:33, Wilbert Knol wrote:
> On Wed, 22 May 2002, Wilson G. Hein wrote:
> > Hi,
> >
> > Trying to patch kerbel 2.4.18 with patch 2.4.19-pre2. Can someone tell me
> > in what RedHat package the patch command is in. Apparently I don't have
> > it
>
> On a related note...I am not sure if this applies to the kernel sources
> Red Hat distibutes...but I haven't had much luck applying official kernel
> patches against 'distributed' kernel source trees.
>
> The patch program generated *lots* of complaints. My impression was, that
> most (if not all)  of those errors related to architectures such as SUN,
> PPC, Alpha etc etc, not supported by my particular distro.
>
> I ended up downloading the 'official' kernel sources from kernel.org..the
> patches worked fine against them.

You said the magic word, "offical kernel source" and offical patches, they go 
together, i can comment on your redhat probs as i always install kernel sorce 
from ftp.kernel.org (patches as well).
 
>
> Also, I found I had to rename the to-be-patched source tree  to 'linux/'
> for the patches to work.

No need, patch has the -p option, all you need to do is go into the dir where 
your linux sorce is and type
gzip -cd /path/to/patch-xx.xx.gz | patch -p1 -s
-s is silent and will only show rejected hunks of patches of which there 
should be none if it was a proper patch for the peroper kernel source.
(At least thats generaly accepted as the case).

>
> On the subject of rolling your own kernel...I find it handy to edit the
> top-level Makefile immediately after the 'make menuconfig' step. At the
> top, you can set a variable. The line looks like this:
>
> EXTRAVERSION = pre99
>
> ...which appends pre99 (just an example) to your kernel version, and also
> to the modules directory
>
> After the 'make modules-install' you can then do a 'make install' which
> copies the new stuff to /boot...this saves you having to copy bzImage and
> setting symlinks, etc, etc.

Doing a make install is according to some (including me) not a good idea 
"unless" you take steps to make sure your old kernel will boot via lilo (or 
whatever bootloader is used).

I always advise coping arch/i386/boot/bzImage to /boot/vmlinuz-xx.xx-prex
and adding a new entry in /ect/lilo.conf then trying lilo with the -t(est) 
option if all is ok then issue /sbin/lilo to install the new kernel.

I have had make install go bad on me and left me to boot with floppy's.
As a matter of fact a better idea when experimenting with new kernels is to 
use make bzdisk and boot from floppy first, that way there is no need to use 
lilo and risk an unbootable system (at the extream of corse).

>
> I haven't seen the 'EXTRAVERSION' and 'make install' things documented
> anywhere (perhaps they are, in RH?), and have found them very handy. As a
> linux-ham, I am always home-brewing kernels.

There is no mention in the Kernel-HOWTO (AFAIK) on the extraversion, there is 
on my home page tho. It explains all and more that i have just disscussed.

I hope this all helps.

>
>
> Wilbert, ZL2BSJ

-- 
Regards Richard
pa3gcu@zeelandnet.nl
http://people.zeelandnet.nl/pa3gcu/


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-05-22 15:04 patch Wilson G. Hein
  2002-05-22 17:44 ` patch Riley Williams
@ 2002-05-23 11:33 ` Wilbert Knol
  2002-05-23 16:01   ` patch Richard Adams
  2002-05-24 14:14   ` patch Tomi Manninen
  1 sibling, 2 replies; 80+ messages in thread
From: Wilbert Knol @ 2002-05-23 11:33 UTC (permalink / raw)
  To: linux-hams

On Wed, 22 May 2002, Wilson G. Hein wrote:

> Hi,
> 
> Trying to patch kerbel 2.4.18 with patch 2.4.19-pre2. Can someone tell me in
> what RedHat package the patch command is in. Apparently I don't have it

On a related note...I am not sure if this applies to the kernel sources 
Red Hat distibutes...but I haven't had much luck applying official kernel 
patches against 'distributed' kernel source trees.

The patch program generated *lots* of complaints. My impression was, that 
most (if not all)  of those errors related to architectures such as SUN, 
PPC, Alpha etc etc, not supported by my particular distro.

I ended up downloading the 'official' kernel sources from kernel.org..the 
patches worked fine against them.

Also, I found I had to rename the to-be-patched source tree  to 'linux/' 
for the patches to work.

On the subject of rolling your own kernel...I find it handy to edit the 
top-level Makefile immediately after the 'make menuconfig' step. At the 
top, you can set a variable. The line looks like this:

EXTRAVERSION = pre99

...which appends pre99 (just an example) to your kernel version, and also 
to the modules directory

After the 'make modules-install' you can then do a 'make install' which 
copies the new stuff to /boot...this saves you having to copy bzImage and 
setting symlinks, etc, etc. 

I haven't seen the 'EXTRAVERSION' and 'make install' things documented 
anywhere (perhaps they are, in RH?), and have found them very handy. As a 
linux-ham, I am always home-brewing kernels.


Wilbert, ZL2BSJ



^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2002-05-22 15:04 patch Wilson G. Hein
@ 2002-05-22 17:44 ` Riley Williams
  2002-05-23 11:33 ` patch Wilbert Knol
  1 sibling, 0 replies; 80+ messages in thread
From: Riley Williams @ 2002-05-22 17:44 UTC (permalink / raw)
  To: Wilson G. Hein; +Cc: Linux-Hams Mailing List

Hi Wilson.

> Trying to patch kerbel 2.4.18 with patch 2.4.19-pre2. Can someone
> tell me in what RedHat package the patch command is in. Apparently I
> don't have it installed:-)

On my system, the package is patch-2.5-10.i386.rpm but the version
number could easily be different on your system.

Best wishes from Riley G7GOD / KB8PPG


^ permalink raw reply	[flat|nested] 80+ messages in thread

* patch
@ 2002-05-22 15:04 Wilson G. Hein
  2002-05-22 17:44 ` patch Riley Williams
  2002-05-23 11:33 ` patch Wilbert Knol
  0 siblings, 2 replies; 80+ messages in thread
From: Wilson G. Hein @ 2002-05-22 15:04 UTC (permalink / raw)
  To: Linux-Hams Mailing List

Hi,

Trying to patch kerbel 2.4.18 with patch 2.4.19-pre2. Can someone tell me in
what RedHat package the patch command is in. Apparently I don't have it
installed:-)

Wilson, WJ3G


^ permalink raw reply	[flat|nested] 80+ messages in thread

* Re: patch
  2001-08-14 15:32 patch Ryan Senior
@ 2001-08-15 12:55 ` Stephen Smalley
  0 siblings, 0 replies; 80+ messages in thread
From: Stephen Smalley @ 2001-08-15 12:55 UTC (permalink / raw)
  To: Ryan Senior; +Cc: SELinux

[-- Attachment #1: Type: TEXT/PLAIN, Size: 612 bytes --]


On Tue, 14 Aug 2001, Ryan Senior wrote:

> patching file initpolicy.conf

The patch is for the kernel-2.4/security/policy_parse.y file, so
it shouldn't be modifying initpolicy.conf at all.  I've attached
a version of the patch that should be easier to apply.  Assuming that you
save it to ~/parser.patch, apply it as follows:

cd slinux
patch -p1 < ~/parser.patch

It should say: patching file kernel-2.4/security/policy_parse.y.

Then do 'cd kernel-2.4; make' to rebuild the checkpolicy program.
You should then be able to compile the policy configuration.

--
Stephen D. Smalley, NAI Labs
ssmalley@nai.com




[-- Attachment #2: Type: TEXT/PLAIN, Size: 915 bytes --]

Index: slinux/kernel-2.4/security/policy_parse.y
diff -u slinux/kernel-2.4/security/policy_parse.y:1.1 slinux/kernel-2.4/security/policy_parse.y:1.2
--- slinux/kernel-2.4/security/policy_parse.y:1.1	Fri Jan  5 14:18:02 2001
+++ slinux/kernel-2.4/security/policy_parse.y	Mon May  7 14:01:23 2001
@@ -1775,7 +1775,6 @@
 {
 	char *id;
 	class_datum_t *cladatum;
-	type_datum_t *datum;
 	perm_datum_t *perdatum;
 	ebitmap_t stypes, ttypes, tclasses;
 	access_vector_t *avp;
@@ -1814,7 +1813,7 @@
 	hiclass = 0;
 	while ((id = queue_remove(id_queue))) {
 		cladatum = hashtab_search(policydbp->p_classes.table, id);
-		if (!datum) {
+		if (!cladatum) {
 			sprintf(errormsg, "unknown class %s used in rule", id);
 			yyerror(errormsg);
 			goto bad;
@@ -2091,7 +2090,6 @@
 		if (ret) {
 			yyerror("hash table overflow");
 			free(role);
-			free(id);
 			free(role_id);
 			return -1;
 		}

^ permalink raw reply	[flat|nested] 80+ messages in thread

* patch
@ 2001-08-14 15:32 Ryan Senior
  2001-08-15 12:55 ` patch Stephen Smalley
  0 siblings, 1 reply; 80+ messages in thread
From: Ryan Senior @ 2001-08-14 15:32 UTC (permalink / raw)
  To: SELinux

I "applied" the patch, but it didn't apply properly.

The following is what I get:

(Stripping trailing CRs from patch.)
patching file initpolicy.conf
Hunk #1 FAILED at 1775.
Hunk #2 FAILED at 1813.
Hunk #3 FAILED at 2090.
3 out of 3 hunks FAILED -- saving rejects to file initpolicy.conf.rej


I am far from an expert at using patch, in fact aside from patching the
kernel, I haven't used patch much at all.  If you need, I could also
paste in what the .rej file says.

Any assistance is appreciated,

Ryan

--
You have received this message because you are subscribed to the selinux list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
@ 2001-07-17 12:54 Cemil Degirmenci
  0 siblings, 0 replies; 80+ messages in thread
From: Cemil Degirmenci @ 2001-07-17 12:54 UTC (permalink / raw)
  To: linux-mtd

----- Forwarded message from David Woodhouse <dwmw2@redhat.com> -----

To: cemil@regio.net
From: David Woodhouse <dwmw2@redhat.com>

Index: drivers/mtd/devices/doc2000.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/devices/doc2000.c,v
retrieving revision 1.43
diff -u -r1.43 doc2000.c
--- drivers/mtd/devices/doc2000.c	2001/06/02 14:30:43	1.43
+++ drivers/mtd/devices/doc2000.c	2001/07/17 12:47:52
@@ -84,19 +84,22 @@
 static int _DoC_WaitReady(struct DiskOnChip *doc)
 {
 	unsigned long docptr = doc->virtadr;
-	unsigned short c = 0xffff;
+	unsigned long timeo = jiffies + (HZ * 10);
 
 	DEBUG(MTD_DEBUG_LEVEL3,
 	      "_DoC_WaitReady called for out-of-line wait\n");
 
 	/* Out-of-line routine to wait for chip response */
-	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
-		;
-
-	if (c == 0)
-		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
+		if (time_after(jiffies, timeo)) {
+			DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+			return -EIO;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
 
-	return (c == 0);
+	return 0;
 }
 
 static inline int DoC_WaitReady(struct DiskOnChip *doc)
@@ -566,6 +569,7 @@
 
 	this->curfloor = -1;
 	this->curchip = -1;
+	init_MUTEX(&this->lock);
 
 	/* Ident all the chips present. */
 	DoC_ScanChips(this);
@@ -606,6 +610,8 @@
 	if (from >= this->totlen)
 		return -EINVAL;
 
+	down(&this->lock);
+
 	/* Don't allow a single read to cross a 512-byte block boundary */
 	if (from + len > ((from | 0x1ff) + 1))
 		len = ((from | 0x1ff) + 1) - from;
@@ -724,6 +730,8 @@
 	    DoC_WaitReady(this);
 	}
 
+	up(&this->lock);
+
 	return ret;
 }
 
@@ -751,6 +759,8 @@
 	if (to >= this->totlen)
 		return -EINVAL;
 
+	down(&this->lock);
+
 	/* Don't allow a single write to cross a 512-byte block boundary */
 	if (to + len > ((to | 0x1ff) + 1))
 		len = ((to | 0x1ff) + 1) - to;
@@ -813,6 +823,7 @@
 			printk("Error programming flash\n");
 			/* Error in programming */
 			*retlen = 0;
+			up(&this->lock);
 			return -EIO;
 		}
 
@@ -865,6 +876,7 @@
 		printk("Error programming flash\n");
 		/* Error in programming */
 		*retlen = 0;
+		up(&this->lock);
 		return -EIO;
 	}
 
@@ -874,6 +886,7 @@
 	if (eccbuf) {
 		unsigned char x[8];
 		size_t dummy;
+		int ret;
 
 		/* Write the ECC data to flash */
 		for (di=0; di<6; di++)
@@ -882,9 +895,11 @@
 		x[6]=0x55;
 		x[7]=0x55;
 		
-		return doc_write_oob(mtd, to, 8, &dummy, x);
+		ret = doc_write_oob(mtd, to, 8, &dummy, x);
+		up(&this->lock);
+		return ret;
 	}
-
+	up(&this->lock);
 	return 0;
 }
 
@@ -892,10 +907,12 @@
 			size_t * retlen, u_char * buf)
 {
 	struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
-	int len256 = 0;
+	int len256 = 0, ret;
 	unsigned long docptr;
 	struct Nand *mychip;
 
+	down(&this->lock);
+
 	docptr = this->virtadr;
 
 	mychip = &this->chips[ofs >> this->chipshift];
@@ -939,12 +956,15 @@
 	/* Reading the full OOB data drops us off of the end of the page,
          * causing the flash device to go into busy mode, so we need
          * to wait until ready 11.4.1 and Toshiba TC58256FT docs */
-	return DoC_WaitReady(this);
+	
+	ret = DoC_WaitReady(this);
+	up(&this->lock);
+	return ret;
 
 }
 
-static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
-			 size_t * retlen, const u_char * buf)
+static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len,
+				size_t * retlen, const u_char * buf)
 {
 	struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
 	int len256 = 0;
@@ -1032,8 +1052,20 @@
 	return 0;
 
 }
+
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
+			 size_t * retlen, const u_char * buf)
+{
+	struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
+	int ret;
+
+	down(&this->lock);
+	ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf);
+	up(&this->lock);
+	return ret;
+}
 
-int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
+static int doc_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv;
 	__u32 ofs = instr->addr;
@@ -1041,6 +1073,8 @@
 	unsigned long docptr;
 	struct Nand *mychip;
 
+	down(&this->lock);
+
 	if (len != mtd->erasesize)
 		printk(KERN_WARNING "Erase not right size (%x != %x)n",
 		       len, mtd->erasesize);
@@ -1078,6 +1112,7 @@
 	if (instr->callback)
 		instr->callback(instr);
 
+	up(&this->lock);
 	return 0;
 }
 
Index: include/linux/mtd/doc2000.h
===================================================================
RCS file: /home/cvs/mtd/include/linux/mtd/doc2000.h,v
retrieving revision 1.13
diff -u -r1.13 doc2000.h
--- include/linux/mtd/doc2000.h	2001/05/29 12:03:45	1.13
+++ include/linux/mtd/doc2000.h	2001/07/17 12:47:52
@@ -134,6 +134,7 @@
 	int numchips;
 	struct Nand *chips;
 	struct mtd_info *nextdoc;
+	struct semaphore lock;
 };
 
 int doc_decode_ecc(unsigned char sector[512], unsigned char ecc1[6]);


----- End forwarded message -----

-- 
Cemil Degirmenci                //   http://cemil.debian-linux.de
Am Eisenberg 13                 //   Tel.       06638-9180010   
36341 Lauterbach                //   Mobil.     0177-2541153
Germany                         //   E-Mail     cemil@security-focus.de

^ permalink raw reply	[flat|nested] 80+ messages in thread

* Patch
@ 1999-05-20 11:54 nicolas.boussekeyt
  0 siblings, 0 replies; 80+ messages in thread
From: nicolas.boussekeyt @ 1999-05-20 11:54 UTC (permalink / raw)
  To: linuxppc-dev, linuxppc-user


I want used the patch find ftp.ppc.kernel.org to my powerbook.
How does i used  this patch in the src of the kernel ?

                                         Nicolas BOUSSEKEYT
                                         ALCATEL Fibre Optique
                                        Tel : 03 21 79 49 00
                                        Web : http://www.alcatel.fr

[[ This message was sent via the linuxppc-dev mailing list.  Replies are ]]
[[ not  forced  back  to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting.   ]]

^ permalink raw reply	[flat|nested] 80+ messages in thread

end of thread, other threads:[~2020-06-23 23:15 UTC | newest]

Thread overview: 80+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-23 22:12 Patch for ip setting on bridge interface and vlan Kevin Yung
2013-01-23 22:51 ` Patch Kevin Yung
  -- strict thread matches above, loose matches on Subject: below --
2020-06-23 23:14 Patch Joe Slater
     [not found] <06c7632e-9e21-7428-bfa3-4ec122f637fd@synopsys.com>
2016-12-27 16:41 ` Patch Joao Pinto
2016-12-27 16:42 ` Patch Joao Pinto
2014-11-30 20:54 PATCH Parth Sane
2014-12-01  2:49 ` PATCH Greg Kroah-Hartman
2014-12-01  5:35   ` PATCH Parth Sane
2014-12-04  1:13     ` PATCH Greg Kroah-Hartman
2013-11-22 16:35 Patch Arthur Schwalbenberg
2013-11-22 17:36 ` Patch Levente Kurusa
2013-11-25  8:58   ` Patch Daniel Vetter
2013-11-25  8:58     ` Patch Daniel Vetter
2010-05-04 16:48 patch Kristoffer Ericson
2009-01-29 10:11 PATCH gabriele.paoloni
2004-10-11  0:01 PATCH Pete Popov
2004-10-11  0:32 ` PATCH Maciej W. Rozycki
2004-10-11  0:47   ` PATCH Pete Popov
2004-10-11  7:55   ` PATCH Pete Popov
2004-10-11 10:32     ` PATCH Christoph Hellwig
2004-10-11 17:07       ` PATCH Pete Popov
2004-10-11 13:53     ` PATCH Atsushi Nemoto
2004-10-11 16:33       ` PATCH Pete Popov
2004-10-11 18:04         ` PATCH Pete Popov
2004-10-10 23:43 PATCH Pete Popov
2004-10-10 17:17 PATCH Pete Popov
2004-10-10 18:01 ` PATCH Geert Uytterhoeven
2004-10-10 19:11   ` PATCH Maciej W. Rozycki
2004-10-10 22:50     ` PATCH Pete Popov
2004-10-11  0:25       ` PATCH Maciej W. Rozycki
2004-10-11  0:39         ` PATCH Pete Popov
2004-10-10 19:33   ` PATCH Matt Porter
2004-10-10 22:52     ` PATCH Pete Popov
2004-10-10 23:41     ` PATCH Pete Popov
2004-10-10  7:17 PATCH Pete Popov
2004-10-10  5:31 PATCH Pete Popov
2004-02-28 22:06 Patch Tommy McCabe
2004-02-22  0:44 PATCH Pete Popov
2004-02-22 16:08 ` PATCH Kronos
2004-02-22 19:03   ` PATCH Pete Popov
2003-12-01  5:58 patch Diyab
2003-12-01 14:36 ` patch Stephen Smalley
2003-11-03 22:45 Patch Frank Borich
2003-11-03 23:00 ` Patch Patrick Mansfield
     [not found] <OE58jbP3SIGYF2rEF6f00001796@hotmail.com>
2003-02-10 16:09 ` Patch Aman
2003-02-10 17:24   ` Patch Matt Porter
2002-12-25 17:36 Patch Mailhebuau Christophe
     [not found] ` <1040837764.2777.8.camel-SH3sQJamR4OeZLLa646FqQ@public.gmane.org>
2002-12-25 19:10   ` Patch Gregory Gulik
2002-12-26  5:12   ` Patch Theodore Morse
2002-12-14  4:52 PATCH Pete Popov
2002-12-17 22:29 ` PATCH Greg Lindahl
2002-12-17 22:40   ` PATCH Pete Popov
2002-12-17 23:24     ` PATCH Alan Cox
2002-12-17 22:51       ` PATCH Pete Popov
2002-12-17 22:59         ` PATCH Greg Lindahl
2002-12-20 20:43 ` PATCH James Simmons
2002-12-20 20:59   ` PATCH Pete Popov
2002-12-21 20:39     ` PATCH James Simmons
2002-12-14  4:50 PATCH Pete Popov
2002-11-18 23:07 patch deepak
2002-11-18 23:20 ` patch Rik van Riel
2002-11-19  7:33   ` patch Duncan Sands
2002-08-26  0:35 patch Russell Coker
2002-08-26 17:15 ` patch Stephen Smalley
2002-08-26 17:37 ` patch Stephen Smalley
2002-07-15 22:29 PATCH Pete Popov
2002-07-16 15:07 ` PATCH Ralf Baechle
2002-07-16 15:15   ` PATCH Pete Popov
2002-07-16 17:43     ` PATCH Joe George
2002-07-16 18:00       ` PATCH Pete Popov
2002-07-17  0:29         ` PATCH Vivien Chappelier
2002-05-22 15:04 patch Wilson G. Hein
2002-05-22 17:44 ` patch Riley Williams
2002-05-23 11:33 ` patch Wilbert Knol
2002-05-23 16:01   ` patch Richard Adams
2002-05-24 14:14   ` patch Tomi Manninen
2001-08-14 15:32 patch Ryan Senior
2001-08-15 12:55 ` patch Stephen Smalley
2001-07-17 12:54 Patch Cemil Degirmenci
1999-05-20 11:54 Patch nicolas.boussekeyt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.